1
0
mirror of https://github.com/GeyserMC/Floodgate.git synced 2025-12-19 14:59:20 +00:00

Merge remote-tracking branch 'origin/dev/2.1.1'

This commit is contained in:
Tim203
2022-05-15 23:59:43 +02:00
223 changed files with 3269 additions and 3185 deletions

View File

@@ -1,6 +1,6 @@
name: Build Pull Request
on: [pull_request]
on: [ pull_request ]
jobs:
build:
@@ -8,34 +8,35 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
uses: actions/setup-java@v2
with:
java-version: 1.8
distribution: 'temurin'
java-version: '8'
cache: 'gradle'
- name: Build with Maven
run: mvn -B package
run: ./gradlew build
- name: Archive artifacts (Floodgate Bungee)
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v2
if: success()
with:
name: Floodgate Bungee
path: bungee/target/floodgate-bungee.jar
path: bungee/build/libs/floodgate-bungee.jar
- name: Archive artifacts (Floodgate Spigot)
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v2
if: success()
with:
name: Floodgate Spigot
path: spigot/target/floodgate-spigot.jar
path: spigot/build/libs/floodgate-spigot.jar
- name: Archive artifacts (Floodgate Velocity)
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v2
if: success()
with:
name: Floodgate Velocity
path: velocity/target/floodgate-velocity.jar
path: velocity/build/libs/floodgate-velocity.jar

4
.gitignore vendored
View File

@@ -219,3 +219,7 @@ nbdist/
.nb-gradle/
# End of https://www.gitignore.io/api/git,java,maven,eclipse,netbeans,jetbrains+all
gradle/
**/.gradle/
/core/src/main/resources/languages/

4
.gitmodules vendored
View File

@@ -1,4 +1,4 @@
[submodule "common/src/main/resources/languages"]
path = common/src/main/resources/languages
[submodule "core/src/main/resources/languages"]
path = core/src/main/resources/languages
url = https://github.com/GeyserMC/languages
branch = l10n_floodgate

View File

@@ -21,8 +21,8 @@
</value>
</option>
<option name="RIGHT_MARGIN" value="100" />
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="ALIGN_MULTILINE_FOR" value="false" />
@@ -59,9 +59,11 @@
</value>
</option>
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<XML>
<option name="XML_ALIGN_ATTRIBUTES" value="false" />
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
<codeStyleSettings language="JAVA">
<option name="RIGHT_MARGIN" value="100" />
@@ -411,5 +413,8 @@
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

41
Jenkinsfile vendored
View File

@@ -1,7 +1,7 @@
pipeline {
agent any
tools {
maven 'Maven 3'
gradle 'Gradle 7'
jdk 'Java 8'
}
options {
@@ -11,11 +11,18 @@ pipeline {
stage ('Build') {
steps {
sh 'git submodule update --init --recursive'
sh 'mvn clean package'
rtGradleRun(
usesPlugin: true,
tool: 'Gradle 7',
buildFile: 'build.gradle.kts',
tasks: 'clean build',
)
}
post {
success {
archiveArtifacts artifacts: '**/target/floodgate-*.jar', excludes: "**/target/floodgate-common.jar", fingerprint: true
archiveArtifacts artifacts: '**/build/libs/floodgate-*.jar',
excludes: '**/floodgate-parent-*.jar,**/floodgate-api.jar,**/floodgate-core.jar',
fingerprint: true
}
}
}
@@ -24,28 +31,30 @@ pipeline {
when {
anyOf {
branch "master"
branch "dev/2.0"
branch "dev/2.1.1"
}
}
steps {
rtMavenDeployer(
id: "maven-deployer",
rtGradleDeployer(
id: "GRADLE_DEPLOYER",
serverId: "opencollab-artifactory",
releaseRepo: "maven-releases",
snapshotRepo: "maven-snapshots"
)
rtMavenResolver(
id: "maven-resolver",
serverId: "opencollab-artifactory",
releaseRepo: "maven-deploy-release",
snapshotRepo: "maven-deploy-snapshot"
rtGradleResolver(
id: "GRADLE_RESOLVER",
serverId: "opencollab-artifactory"
)
rtMavenRun(
pom: 'pom.xml',
goals: 'source:jar install -DskipTests',
deployerId: "maven-deployer",
resolverId: "maven-resolver"
rtGradleRun(
usesPlugin: true,
tool: 'Gradle 7',
rootDir: "",
useWrapper: true,
buildFile: 'build.gradle.kts',
tasks: 'artifactoryPublish',
deployerId: "GRADLE_DEPLOYER",
resolverId: "GRADLE_RESOLVER"
)
rtPublishBuildInfo(
serverId: "opencollab-artifactory"

View File

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

6
api/build.gradle.kts Normal file
View File

@@ -0,0 +1,6 @@
dependencies {
api("org.geysermc", "common", Versions.geyserVersion)
api("org.geysermc.cumulus", "cumulus", Versions.cumulusVersion)
compileOnly("io.netty", "netty-transport", Versions.nettyVersion)
}

View File

@@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>parent</artifactId>
<groupId>org.geysermc.floodgate</groupId>
<version>2.1.0-SNAPSHOT</version>
</parent>
<artifactId>api</artifactId>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<version>${netty.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>common</artifactId>
<version>${geyser.version}</version>
</dependency>
<dependency>
<groupId>org.geysermc.cumulus</groupId>
<artifactId>cumulus</artifactId>
<version>${cumulus.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>opencollab-release-repo</id>
<url>https://repo.opencollab.dev/maven-releases/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>opencollab-snapshot-repo</id>
<url>https://repo.opencollab.dev/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<finalName>${outputName}</finalName>
<shadedArtifactAttached>true</shadedArtifactAttached>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,6 +32,7 @@ import org.geysermc.cumulus.Form;
import org.geysermc.cumulus.util.FormBuilder;
import org.geysermc.floodgate.api.link.PlayerLink;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.geysermc.floodgate.api.unsafe.Unsafe;
public interface FloodgateApi {
/**
@@ -139,4 +140,6 @@ public interface FloodgateApi {
default PlayerLink getPlayerLink() {
return InstanceHolder.getPlayerLink();
}
Unsafe unsafe();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -34,7 +34,7 @@ public interface InjectorAddon {
* used for third party things.
*
* @param channel the channel that the injector is injecting
* @param toServer if the the connection is between a proxy and a server
* @param toServer if the connection is between a proxy and a server
*/
void onInject(Channel channel, boolean toServer);
@@ -43,7 +43,7 @@ public interface InjectorAddon {
* closed connection (if it is injected), so it'll also run this method for closed connections
* between a server and the proxy (when Floodgate is running on a proxy).
*
* @param channel the channel that the injecor injected
* @param channel the channel that the injector injected
*/
default void onChannelClosed(Channel channel) {
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -51,7 +51,7 @@ public class PropertyKey {
this.removable = removable;
}
public Result isAddAllowed(Object obj) { //todo use for add and remove
public Result isAddAllowed(Object obj) {
if (obj instanceof PropertyKey) {
PropertyKey propertyKey = (PropertyKey) obj;

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.api.unsafe;
import java.util.UUID;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
public interface Unsafe {
/**
* Send a raw Bedrock packet to the given online Bedrock player.
*
* @param bedrockPlayer the uuid of the online Bedrock player
* @param packetId the id of the packet to send
* @param packetData the raw packet data
*/
void sendPacket(UUID bedrockPlayer, int packetId, byte[] packetData);
/**
* Send a raw Bedrock packet to the given online Bedrock player.
*
* @param player the Bedrock player to send the packet to
* @param packetId the id of the packet to send
* @param packetData the raw packet data
*/
default void sendPacket(FloodgatePlayer player, int packetId, byte[] packetData) {
sendPacket(player.getCorrectUniqueId(), packetId, packetData);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,21 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
`kotlin-dsl`
}
repositories {
gradlePluginPortal()
}
dependencies {
implementation("net.kyori", "indra-common", "2.0.6")
implementation("org.jfrog.buildinfo", "build-info-extractor-gradle", "4.26.1")
implementation("gradle.plugin.com.github.johnrengelman", "shadow", "7.1.1")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
object Versions {
const val geyserVersion = "2.0.0-SNAPSHOT"
const val cumulusVersion = "1.0-SNAPSHOT"
const val configUtilsVersion = "1.0-SNAPSHOT"
const val spigotVersion = "1.13-R0.1-SNAPSHOT"
const val fastutilVersion = "8.5.3"
const val lombokVersion = "1.18.20"
const val guiceVersion = "5.0.1"
const val nettyVersion = "4.1.49.Final"
const val snakeyamlVersion = "1.28"
const val cloudVersion = "1.5.0"
const val bstatsVersion = "3.0.0"
const val javaWebsocketVersion = "1.5.2"
const val checkerQual = "3.19.0"
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
import net.kyori.indra.git.IndraGitExtension
import org.gradle.api.Project
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.kotlin.dsl.the
fun Project.isSnapshot(): Boolean =
version.toString().endsWith("-SNAPSHOT")
fun Project.fullVersion(): String {
var version = version.toString()
if (version.endsWith("-SNAPSHOT")) {
version += " (b${buildNumberAsString()}-${lastCommitHash()})"
}
return version
}
fun Project.lastCommitHash(): String? =
the<IndraGitExtension>().commit()?.name?.substring(0, 7)
// retrieved from https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project
// some properties might be specific to Jenkins
fun Project.branchName(): String =
System.getenv("GIT_BRANCH") ?: "local/dev"
fun Project.buildNumber(): Int =
Integer.parseInt(System.getenv("BUILD_NUMBER") ?: "-1")
fun Project.buildNumberAsString(): String =
buildNumber().takeIf { it != -1 }?.toString() ?: "??"
val providedDependencies = mutableMapOf<String, MutableSet<String>>()
val relocatedPackages = mutableMapOf<String, MutableSet<String>>()
fun Project.provided(pattern: String, name: String, version: String, excludedOn: Int = 0b110) {
providedDependencies.getOrPut(project.name) { mutableSetOf() }
.add("${calcExclusion(pattern, 0b100, excludedOn)}:" +
"${calcExclusion(name, 0b10, excludedOn)}:" +
calcExclusion(version, 0b1, excludedOn))
dependencies.add("compileOnlyApi", "$pattern:$name:$version")
}
fun Project.provided(dependency: ProjectDependency) =
provided(dependency.group!!, dependency.name, dependency.version!!)
fun Project.relocate(pattern: String) =
relocatedPackages.getOrPut(project.name) { mutableSetOf() }
.add(pattern)
private fun calcExclusion(section: String, bit: Int, excludedOn: Int): String =
if (excludedOn and bit > 0) section else ""

View File

@@ -0,0 +1,35 @@
plugins {
`java-library`
`maven-publish`
// id("net.ltgt.errorprone")
id("net.kyori.indra.git")
}
dependencies {
compileOnly("org.checkerframework", "checker-qual", Versions.checkerQual)
}
tasks {
processResources {
filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json")) {
expand(
"id" to "floodgate",
"name" to "floodgate",
"version" to fullVersion(),
"description" to project.description,
"url" to "https://geysermc.org",
"author" to "GeyserMC"
)
}
}
compileJava {
options.encoding = Charsets.UTF_8.name()
}
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
withSourcesJar()
}

View File

@@ -0,0 +1,9 @@
plugins {
id("floodgate.shadow-conventions")
}
tasks {
shadowJar {
archiveBaseName.set(archiveBaseName.get() + "-database")
}
}

View File

@@ -0,0 +1,34 @@
plugins {
id("floodgate.shadow-conventions")
id("com.jfrog.artifactory")
id("maven-publish")
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
groupId = project.group as String
artifactId = project.name
version = project.version as String
artifact(tasks["shadowJar"])
artifact(tasks["sourcesJar"])
}
}
}
artifactory {
setContextUrl("https://repo.opencollab.dev/artifactory")
publish {
repository {
setRepoKey(if (isSnapshot()) "maven-snapshots" else "maven-releases")
setMavenCompatible(true)
}
defaults {
publications("mavenJava")
setPublishArtifacts(true)
setPublishPom(true)
setPublishIvy(false)
}
}
}

View File

@@ -0,0 +1,54 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins {
id("floodgate.base-conventions")
id("com.github.johnrengelman.shadow")
}
tasks {
named<Jar>("jar") {
archiveClassifier.set("unshaded")
from(project.rootProject.file("LICENSE"))
}
val shadowJar = named<ShadowJar>("shadowJar") {
archiveBaseName.set("floodgate-${project.name}")
archiveVersion.set("")
archiveClassifier.set("")
val sJar: ShadowJar = this
doFirst {
providedDependencies[project.name]?.forEach { string ->
sJar.dependencies {
println("Excluding $string from ${project.name}")
exclude(dependency(string))
}
}
// relocations made in included project dependencies are for whatever reason not
// forwarded to the project implementing the dependency.
// (e.g. a relocation in `core` will relocate for core. But when you include `core` in
// for example Velocity, the relocation will be gone for Velocity)
addRelocations(project, sJar)
}
}
named("build") {
dependsOn(shadowJar)
}
}
fun addRelocations(project: Project, shadowJar: ShadowJar) {
callAddRelocations(project.configurations.api.get(), shadowJar)
callAddRelocations(project.configurations.implementation.get(), shadowJar)
relocatedPackages[project.name]?.forEach { pattern ->
println("Relocating $pattern for ${shadowJar.project.name}")
shadowJar.relocate(pattern, "org.geysermc.floodgate.shadow.$pattern")
}
}
fun callAddRelocations(configuration: Configuration, shadowJar: ShadowJar) =
configuration.dependencies.forEach {
if (it is ProjectDependency)
addRelocations(it.dependencyProject, shadowJar)
}

54
build.gradle.kts Normal file
View File

@@ -0,0 +1,54 @@
plugins {
`java-library`
id("floodgate.build-logic")
// id("com.github.spotbugs") version "4.8.0" apply false
id("io.freefair.lombok") version "6.3.0" apply false
// checkstyle
}
allprojects {
group = "org.geysermc.floodgate"
version = "2.1.1-SNAPSHOT"
description = "Allows Bedrock players to join Java edition servers while keeping the server in online mode"
}
val deployProjects = setOf(
projects.api,
// for future Floodgate integration + Fabric
projects.core,
projects.bungee,
projects.spigot,
projects.velocity
).map { it.dependencyProject }
//todo re-add pmd and organisation/license/sdcm/issuemanagement stuff
subprojects {
// apply(plugin = "com.github.spotbugs")
apply {
plugin("java-library")
// plugin("checkstyle")
plugin("io.freefair.lombok")
plugin("floodgate.build-logic")
}
// checkstyle {
// toolVersion = "9.3"
// configFile = rootProject.projectDir.resolve("checkstyle.xml")
// maxErrors = 0
// maxWarnings = 0
// }
val relativePath = projectDir.relativeTo(rootProject.projectDir).path
if (relativePath.startsWith("database" + File.separator)) {
group = rootProject.group as String + ".database"
plugins.apply("floodgate.database-conventions")
}
when (this) {
in deployProjects -> plugins.apply("floodgate.publish-conventions")
else -> plugins.apply("floodgate.base-conventions")
}
}

20
bungee/build.gradle.kts Normal file
View File

@@ -0,0 +1,20 @@
var bungeeCommit = "bda1605"
var gsonVersion = "2.8.0"
var guavaVersion = "21.0"
dependencies {
api(projects.core)
implementation("cloud.commandframework", "cloud-bungee", Versions.cloudVersion)
}
relocate("com.google.inject")
relocate("net.kyori")
relocate("cloud.commandframework")
// used in cloud
relocate("io.leangen.geantyref")
// these dependencies are already present on the platform
provided("com.github.SpigotMC.BungeeCord", "bungeecord-proxy", bungeeCommit)
provided("com.google.code.gson", "gson", gsonVersion)
provided("com.google.guava", "guava", guavaVersion)
provided("org.yaml", "snakeyaml", Versions.snakeyamlVersion)

View File

@@ -1,129 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>parent</artifactId>
<groupId>org.geysermc.floodgate</groupId>
<version>2.1.0-SNAPSHOT</version>
</parent>
<artifactId>bungee</artifactId>
<properties>
<bungeecord.commit>bda1605</bungeecord.commit>
<gson.version>2.8.0</gson.version>
<guava.version>21.0</guava.version>
</properties>
<dependencies>
<dependency>
<groupId>com.github.SpigotMC.BungeeCord</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>${bungeecord.commit}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
<!-- following dependencies are relocated -->
<dependency>
<groupId>cloud.commandframework</groupId>
<artifactId>cloud-bungee</artifactId>
<version>${cloud.version}</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-gson</artifactId>
<version>${adventure-api.version}</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-bungeecord</artifactId>
<version>${adventure-platform.version}</version>
</dependency>
<!-- the following common dependencies are already present on the platform -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>bungeecord-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
<repository>
<id>jitpack</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>com.google.inject</pattern>
<shadedPattern>org.geysermc.floodgate.shaded.com.google.inject</shadedPattern>
</relocation>
<relocation>
<pattern>net.kyori</pattern>
<shadedPattern>org.geysermc.floodgate.shaded.net.kyori</shadedPattern>
</relocation>
<relocation>
<pattern>cloud.commandframework</pattern>
<shadedPattern>org.geysermc.floodgate.shaded.cloud.commandframework</shadedPattern>
</relocation>
<!-- used in cloud -->
<relocation>
<pattern>io.leangen.geantyref</pattern>
<shadedPattern>org.geysermc.floodgate.shaded.io.leangen.geantyref</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
<configuration>
<finalName>${outputName}</finalName>
<shadedArtifactAttached>true</shadedArtifactAttached>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -86,7 +86,7 @@ public class BungeeDataAddon implements InjectorAddon {
@Override
public void onChannelClosed(Channel channel) {
FloodgatePlayer player = channel.attr(playerAttribute).get();
if (player != null && api.removePlayer(player)) {
if (player != null && api.setPendingRemove(player)) {
logger.translatedInfo("floodgate.ingame.disconnect_name", player.getCorrectUsername());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -59,7 +59,7 @@ public final class BungeeInjector extends CommonPlatformInjector {
// (Instead of just replacing the ChannelInitializer which is only called for
// player <-> proxy)
BungeeCustomPrepender customPrepender = new BungeeCustomPrepender(
this, ReflectionUtils.getCastedValue(null, framePrepender)
this, ReflectionUtils.castedStaticValue(framePrepender)
);
BungeeReflectionUtils.setFieldValue(null, framePrepender, customPrepender);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,10 +46,9 @@ import net.md_5.bungee.netty.ChannelWrapper;
import org.geysermc.floodgate.api.ProxyFloodgateApi;
import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.geysermc.floodgate.player.FloodgatePlayerImpl;
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
import org.geysermc.floodgate.skin.SkinApplier;
import org.geysermc.floodgate.skin.SkinData;
import org.geysermc.floodgate.util.BungeeCommandUtil;
import org.geysermc.floodgate.util.LanguageManager;
import org.geysermc.floodgate.util.ReflectionUtils;
@@ -67,6 +66,7 @@ public final class BungeeListener implements Listener {
checkNotNull(PLAYER_NAME, "Initial name field cannot be null");
}
@Inject private ProxyFloodgateConfig config;
@Inject private ProxyFloodgateApi api;
@Inject private LanguageManager languageManager;
@Inject private FloodgateLogger logger;
@@ -115,7 +115,8 @@ public final class BungeeListener implements Listener {
UUID uniqueId = event.getConnection().getUniqueId();
FloodgatePlayer player = api.getPlayer(uniqueId);
if (player != null) {
player.as(FloodgatePlayerImpl.class).setLogin(false);
//todo we should probably move this log message earlier in the process, so that we know
// that Floodgate has done its job
logger.translatedInfo(
"floodgate.ingame.login_name",
player.getCorrectUsername(), uniqueId
@@ -127,14 +128,16 @@ public final class BungeeListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onPostLogin(PostLoginEvent event) {
// To fix the February 2 2022 Mojang authentication changes
if (!config.isSendFloodgateData()) {
FloodgatePlayer player = api.getPlayer(event.getPlayer().getUniqueId());
if (player != null) {
if (player != null && !player.isLinked()) {
skinApplier.applySkin(player, new SkinData("", ""));
}
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerDisconnect(PlayerDisconnectEvent event) {
BungeeCommandUtil.AUDIENCE_CACHE.remove(event.getPlayer().getUniqueId()); //todo
api.playerRemoved(event.getPlayer().getUniqueId());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,6 +46,7 @@ import org.geysermc.floodgate.logger.JavaUtilFloodgateLogger;
import org.geysermc.floodgate.platform.command.CommandUtil;
import org.geysermc.floodgate.platform.listener.ListenerRegistration;
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageUtils;
import org.geysermc.floodgate.platform.util.PlatformUtils;
import org.geysermc.floodgate.player.FloodgateCommandPreprocessor;
import org.geysermc.floodgate.player.UserAudience;
import org.geysermc.floodgate.pluginmessage.BungeePluginMessageRegistration;
@@ -55,12 +56,18 @@ import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
import org.geysermc.floodgate.pluginmessage.PluginMessageRegistration;
import org.geysermc.floodgate.skin.SkinApplier;
import org.geysermc.floodgate.util.BungeeCommandUtil;
import org.geysermc.floodgate.util.BungeePlatformUtils;
import org.geysermc.floodgate.util.LanguageManager;
@RequiredArgsConstructor
public final class BungeePlatformModule extends AbstractModule {
private final BungeePlugin plugin;
@Override
protected void configure() {
bind(PlatformUtils.class).to(BungeePlatformUtils.class);
}
@Provides
@Singleton
public Plugin bungeePlugin() {
@@ -83,7 +90,7 @@ public final class BungeePlatformModule extends AbstractModule {
CommandManager<UserAudience> commandManager = new BungeeCommandManager<>(
plugin,
CommandExecutionCoordinator.simpleCoordinator(),
commandUtil::getAudience,
commandUtil::getUserAudience,
audience -> (CommandSender) audience.source()
);
commandManager.registerCommandPreProcessor(new FloodgateCommandPreprocessor<>(commandUtil));
@@ -92,11 +99,8 @@ public final class BungeePlatformModule extends AbstractModule {
@Provides
@Singleton
public CommandUtil commandUtil(
FloodgateApi api,
FloodgateLogger logger,
LanguageManager languageManager) {
return new BungeeCommandUtil(plugin.getProxy(), api, logger, languageManager);
public CommandUtil commandUtil(FloodgateApi api, LanguageManager languageManager) {
return new BungeeCommandUtil(languageManager, plugin.getProxy(), api);
}
@Provides

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,29 @@
package org.geysermc.floodgate.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.platform.command.CommandUtil;
import org.geysermc.floodgate.platform.command.TranslatableMessage;
import org.geysermc.floodgate.player.UserAudience;
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
import org.geysermc.floodgate.util.BungeeUserAudience.BungeeConsoleAudience;
import org.geysermc.floodgate.util.BungeeUserAudience.BungeePlayerAudience;
@RequiredArgsConstructor
public final class BungeeCommandUtil implements CommandUtil {
public static final @NonNull Map<UUID, UserAudience> AUDIENCE_CACHE = new HashMap<>();
private static UserAudience console;
import org.geysermc.floodgate.player.UserAudience.ConsoleAudience;
import org.geysermc.floodgate.player.UserAudience.PlayerAudience;
public final class BungeeCommandUtil extends CommandUtil {
private final ProxyServer server;
private final FloodgateApi api;
private UserAudience console;
private final FloodgateLogger logger;
private final LanguageManager manager;
public BungeeCommandUtil(LanguageManager manager, ProxyServer server, FloodgateApi api) {
super(manager, api);
this.server = server;
}
@Override
public @NonNull UserAudience getAudience(@NonNull Object sourceObj) {
public @NonNull UserAudience getUserAudience(@NonNull Object sourceObj) {
if (!(sourceObj instanceof CommandSender)) {
throw new IllegalArgumentException("Can only work with CommandSource!");
}
@@ -70,7 +57,7 @@ public final class BungeeCommandUtil implements CommandUtil {
if (console != null) {
return console;
}
return console = new BungeeConsoleAudience(source, this);
return console = new ConsoleAudience(source, this);
}
ProxiedPlayer player = (ProxiedPlayer) source;
@@ -78,82 +65,39 @@ public final class BungeeCommandUtil implements CommandUtil {
String username = player.getName();
String locale = Utils.getLocale(player.getLocale());
return AUDIENCE_CACHE.computeIfAbsent(uuid,
$ -> new BungeePlayerAudience(uuid, username, locale, source, true, this));
return new PlayerAudience(uuid, username, locale, source, this, true);
}
@Override
public @Nullable UserAudience getAudienceByUsername(@NonNull String username) {
ProxiedPlayer player = server.getPlayer(username);
return player != null ? getAudience(player) : null;
protected String getUsernameFromSource(@NonNull Object source) {
return ((ProxiedPlayer) source).getName();
}
@Override
public @NonNull UserAudience getOfflineAudienceByUsername(@NonNull String username) {
return new BungeePlayerAudience(null, username, null, null, false, this);
protected UUID getUuidFromSource(@NonNull Object source) {
return ((ProxiedPlayer) source).getUniqueId();
}
@Override
public @Nullable UserAudience getAudienceByUuid(@NonNull UUID uuid) {
protected Collection<?> getOnlinePlayers() {
return server.getPlayers();
}
@Override
public Object getPlayerByUuid(@NonNull UUID uuid) {
ProxiedPlayer player = server.getPlayer(uuid);
return player != null ? getAudience(player) : null;
return player != null ? player : uuid;
}
@Override
public @NonNull UserAudience getOfflineAudienceByUuid(@NonNull UUID uuid) {
return new BungeePlayerAudience(uuid, null, null, null, false, this);
}
@Override
public @NonNull Collection<String> getOnlineUsernames(@NonNull PlayerType limitTo) {
Collection<ProxiedPlayer> players = server.getPlayers();
Collection<String> usernames = new ArrayList<>();
switch (limitTo) {
case ALL_PLAYERS:
for (ProxiedPlayer player : players) {
usernames.add(player.getName());
}
break;
case ONLY_JAVA:
for (ProxiedPlayer player : players) {
if (!api.isFloodgatePlayer(player.getUniqueId())) {
usernames.add(player.getName());
}
}
break;
case ONLY_BEDROCK:
for (ProxiedPlayer player : players) {
if (api.isFloodgatePlayer(player.getUniqueId())) {
usernames.add(player.getName());
}
}
break;
default:
throw new IllegalStateException("Unknown PlayerType");
}
return usernames;
public Object getPlayerByUsername(@NonNull String username) {
ProxiedPlayer player = server.getPlayer(username);
return player != null ? player : username;
}
@Override
public boolean hasPermission(Object player, String permission) {
return cast(player).hasPermission(permission);
}
@Override
public Collection<Object> getOnlinePlayersWithPermission(String permission) {
List<Object> players = new ArrayList<>();
for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
if (hasPermission(player, permission)) {
players.add(player);
}
}
return players;
}
@Override
public void sendMessage(Object target, String locale, TranslatableMessage message, Object... args) {
((CommandSender) target).sendMessage(translateAndTransform(locale, message, args));
return ((CommandSender) player).hasPermission(permission);
}
@Override
@@ -162,23 +106,10 @@ public final class BungeeCommandUtil implements CommandUtil {
}
@Override
public void kickPlayer(Object player, String locale, TranslatableMessage message, Object... args) {
cast(player).disconnect(translateAndTransform(locale, message, args));
}
public BaseComponent[] translateAndTransform(
String locale,
TranslatableMessage message,
Object... args) {
return TextComponent.fromLegacyText(message.translateMessage(manager, locale, args));
}
protected ProxiedPlayer cast(Object player) {
try {
return (ProxiedPlayer) player;
} catch (ClassCastException exception) {
logger.error("Failed to cast {} to ProxiedPlayer", player.getClass().getName());
throw exception;
public void kickPlayer(Object player, String message) {
// can also be a console
if (player instanceof ProxiedPlayer) {
((ProxiedPlayer) player).disconnect(message);
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.util;
import java.lang.reflect.Field;
import java.util.List;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.protocol.ProtocolConstants;
import org.geysermc.floodgate.platform.util.PlatformUtils;
@SuppressWarnings("ConstantConditions")
public final class BungeePlatformUtils extends PlatformUtils {
private static final String LATEST_SUPPORTED_VERSION;
private final ProxyServer proxyServer = ProxyServer.getInstance();
static {
int protocolNumber = -1;
String versionName = "";
for (Field field : ProtocolConstants.class.getFields()) {
if (!field.getName().startsWith("MINECRAFT_")) {
continue;
}
int fieldValue = ReflectionUtils.castedStaticValue(field);
if (fieldValue > protocolNumber) {
protocolNumber = fieldValue;
versionName = field.getName().substring(10).replace('_', '.');
}
}
if (protocolNumber == -1) {
List<String> versions = ProtocolConstants.SUPPORTED_VERSIONS;
versionName = versions.get(versions.size() - 1);
}
LATEST_SUPPORTED_VERSION = versionName;
}
@Override
public AuthType authType() {
return proxyServer.getConfig().isOnlineMode() ? AuthType.ONLINE : AuthType.OFFLINE;
}
@Override
public String minecraftVersion() {
return LATEST_SUPPORTED_VERSION;
}
@Override
public String serverImplementationName() {
return proxyServer.getName();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,159 +0,0 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.util;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.ForwardingAudience;
import net.kyori.adventure.audience.MessageType;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.floodgate.platform.command.CommandUtil;
import org.geysermc.floodgate.platform.command.TranslatableMessage;
import org.geysermc.floodgate.player.UserAudience;
@RequiredArgsConstructor
public class BungeeUserAudience implements UserAudience, ForwardingAudience.Single {
private final UUID uuid;
private final String locale;
private final CommandSender source;
private final CommandUtil commandUtil;
@Override
public @NonNull UUID uuid() {
return uuid;
}
@Override
public @NonNull String username() {
return source.getName();
}
@Override
public @NonNull String locale() {
return locale;
}
@Override
public @NonNull CommandSender source() {
return source;
}
@Override
public boolean hasPermission(@NonNull String permission) {
return source.hasPermission(permission);
}
@Override
public void sendMessage(
@NonNull Identity source,
@NonNull Component message,
@NonNull MessageType type) {
this.source.sendMessage(GsonComponentSerializer.gson().serialize(message));
}
@Override
public void sendMessage(TranslatableMessage message, Object... args) {
commandUtil.sendMessage(source(), locale(), message, args);
}
@Override
public void disconnect(@NonNull Component reason) {
if (source instanceof ProxiedPlayer) {
((ProxiedPlayer) source).disconnect(GsonComponentSerializer.gson().serialize(reason));
}
}
@Override
public void disconnect(TranslatableMessage message, Object... args) {
commandUtil.kickPlayer(source(), locale(), message, args);
}
@Override
public @NonNull Audience audience() {
return this;
}
public static final class BungeeConsoleAudience extends BungeeUserAudience
implements ConsoleAudience {
public BungeeConsoleAudience(CommandSender source, CommandUtil commandUtil) {
super(new UUID(0, 0), "en_us", source, commandUtil);
}
@Override
public void sendMessage(
@NonNull Identity source,
@NonNull Component message,
@NonNull MessageType type) {
source().sendMessage(BungeeComponentSerializer.get().serialize(message));
}
}
public static final class BungeePlayerAudience extends BungeeUserAudience
implements PlayerAudience {
private final String username;
private final boolean online;
public BungeePlayerAudience(
UUID uuid,
String username,
String locale,
CommandSender source,
boolean online,
CommandUtil commandUtil) {
super(uuid, locale, source, commandUtil);
this.username = username;
this.online = online;
}
public BungeePlayerAudience(
UUID uuid,
String locale,
CommandSender source,
boolean online,
CommandUtil commandUtil) {
this(uuid, source.getName(), locale, source, online, commandUtil);
}
@Override
public @NonNull String username() {
return username;
}
@Override
public boolean online() {
return online;
}
}
}

View File

@@ -1,5 +1,5 @@
name: ${project.parent.name}
description: ${project.description}
version: ${project.version}
author: ${project.organization.name}
name: ${name}
description: ${description}
version: ${version}
author: ${author}
main: org.geysermc.floodgate.BungeePlugin

364
checkstyle.xml Normal file
View File

@@ -0,0 +1,364 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--
Checkstyle configuration that checks the Google coding conventions from Google Java Style
that can be found at https://google.github.io/styleguide/javaguide.html
Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.org (or in your downloaded distribution).
To completely disable a check, just comment it out or delete it from the file.
To suppress certain violations please review suppression filters.
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<module name = "Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Excludes all 'module-info.java' files -->
<!-- See https://checkstyle.org/config_filefilters.html -->
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
<!-- https://checkstyle.org/config_filters.html#SuppressionFilter -->
<module name="SuppressionFilter">
<property name="file" value="${org.checkstyle.google.suppressionfilter.config}"
default="checkstyle-suppressions.xml" />
<property name="optional" value="true"/>
</module>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.org/config_whitespace.html -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="LineLength">
<property name="fileExtensions" value="java"/>
<property name="max" value="100"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="TreeWalker">
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap">
<property name="tokens" value="PACKAGE_DEF, IMPORT, STATIC_IMPORT"/>
</module>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces">
<property name="tokens"
value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE"/>
</module>
<module name="LeftCurly">
<property name="tokens"
value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
OBJBLOCK, STATIC_INIT, RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/>
</module>
<module name="SuppressionXpathSingleFilter">
<!-- suppresion is required till https://github.com/checkstyle/checkstyle/issues/7541 -->
<property name="id" value="RightCurlyAlone"/>
<property name="query" value="//RCURLY[parent::SLIST[count(./*)=1]
or preceding-sibling::*[last()][self::LCURLY]]"/>
</module>
<module name="WhitespaceAfter">
<property name="tokens"
value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE,
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, DO_WHILE"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyLambdas" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<property name="ignoreEnhancedForColon" value="false"/>
<property name="tokens"
value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="tokens"
value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/>
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapDot"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapComma"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/259 -->
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/258 -->
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapMethodRef"/>
<property name="tokens" value="METHOD_REF"/>
<property name="option" value="nl"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
ANNOTATION_DEF, RECORD_DEF"/>
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="PatternVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Pattern variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordComponentName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Record component name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Record type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Indentation">
<property name="basicOffset" value="2"/>
<property name="braceAdjustment" value="2"/>
<property name="caseIndent" value="2"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="2"/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="0"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF,
RECORD_COMPONENT_DEF"/>
</module>
<module name="NoWhitespaceBeforeCaseDefaultColon"/>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
<property name="tokens" value="IMPORT, STATIC_IMPORT, PACKAGE_DEF"/>
</module>
<module name="MethodParamPad">
<property name="tokens"
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
SUPER_CTOR_CALL, ENUM_CONSTANT_DEF, RECORD_DEF"/>
</module>
<module name="NoWhitespaceBefore">
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT,
LABELED_STAT, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="ParenPad">
<property name="tokens"
value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA,
RECORD_DEF"/>
</module>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF,
TYPE_EXTENSION_AND "/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF,
RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="InvalidJavadocPosition"/>
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph"/>
<module name="RequireEmptyLineBeforeBlockTagGroup"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="JavadocMethod">
<property name="accessModifiers" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="MissingJavadocMethod">
<property name="scope" value="public"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF,
COMPACT_CTOR_DEF"/>
</module>
<module name="MissingJavadocType">
<property name="scope" value="protected"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
RECORD_DEF, ANNOTATION_DEF"/>
<property name="excludeScope" value="nothing"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc"/>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
<module name="CommentsIndentation">
<property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN"/>
</module>
<!-- https://checkstyle.org/config_filters.html#SuppressionXpathFilter -->
<module name="SuppressionXpathFilter">
<property name="file" value="${org.checkstyle.google.suppressionxpathfilter.config}"
default="checkstyle-xpath-suppressions.xml" />
<property name="optional" value="true"/>
</module>
</module>
</module>

View File

@@ -1,133 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>parent</artifactId>
<groupId>org.geysermc.floodgate</groupId>
<version>2.1.0-SNAPSHOT</version>
</parent>
<artifactId>common</artifactId>
<properties>
<java-websocket.version>1.5.2</java-websocket.version>
</properties>
<dependencies>
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.geysermc.cumulus</groupId>
<artifactId>cumulus</artifactId>
<version>${cumulus.version}</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>${guice.version}</version>
</dependency>
<dependency>
<groupId>com.nukkitx.fastutil</groupId>
<artifactId>fastutil-short-object-maps</artifactId>
<version>${fastutil.version}</version>
</dependency>
<dependency>
<groupId>com.nukkitx.fastutil</groupId>
<artifactId>fastutil-int-object-maps</artifactId>
<version>${fastutil.version}</version>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>${java-websocket.version}</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>${adventure-api.version}</version>
</dependency>
<dependency>
<groupId>cloud.commandframework</groupId>
<artifactId>cloud-core</artifactId>
<version>${cloud.version}</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version>
</dependency>
<!-- present on all platforms -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<version>${netty.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec</artifactId>
<version>${netty.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>opencollab-release-repo</id>
<url>https://repo.opencollab.dev/maven-releases/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>opencollab-snapshot-repo</id>
<url>https://repo.opencollab.dev/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>minecraft-libraries</id>
<name>Minecraft Libraries</name>
<url>https://libraries.minecraft.net</url>
</repository>
<repository>
<id>paper repo</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<finalName>${outputName}</finalName>
<shadedArtifactAttached>true</shadedArtifactAttached>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,109 +0,0 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.config.loader;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.LinkedHashMap;
import java.util.Map;
import org.geysermc.floodgate.config.FloodgateConfig;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor;
import org.yaml.snakeyaml.introspector.BeanAccess;
import org.yaml.snakeyaml.introspector.FieldProperty;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.introspector.PropertyUtils;
public class ConfigInitializer {
private static final Yaml YAML;
static {
Constructor constructor =
new CustomClassLoaderConstructor(ConfigInitializer.class.getClassLoader());
constructor.setPropertyUtils(new PropertyUtils() {
@Override
protected Map<String, Property> getPropertiesMap(Class<?> type, BeanAccess bAccess) {
Map<String, Property> properties = new LinkedHashMap<>();
getPropertiesFromClass(type, FloodgateConfig.class, properties);
return properties;
}
private void getPropertiesFromClass(
Class<?> type,
Class<?> stopAfter,
Map<String, Property> propertyMap) {
Class<?> current = type;
while (!Object.class.equals(current)) {
for (Field field : current.getDeclaredFields()) {
int modifiers = field.getModifiers();
if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)) {
String correctName = getCorrectName(field.getName());
// children should override parents
propertyMap.putIfAbsent(correctName, new FieldProperty(field));
}
if (field.getClass().getSuperclass().equals(current)) {
getPropertiesFromClass(field.getClass(), field.getClass(), propertyMap);
}
}
if (current.equals(stopAfter)) {
return;
}
current = type.getSuperclass();
}
}
private String getCorrectName(String name) {
// convert sendFloodgateData to send-floodgate-data,
// which is the style of writing config fields
StringBuilder propertyBuilder = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
char current = name.charAt(i);
if (Character.isUpperCase(current)) {
propertyBuilder.append('-').append(Character.toLowerCase(current));
} else {
propertyBuilder.append(current);
}
}
return propertyBuilder.toString();
}
});
constructor.getPropertyUtils().setSkipMissingProperties(true);
YAML = new Yaml(constructor);
}
public static <T extends FloodgateConfig> T initializeFrom(
InputStream dataStream,
Class<T> configClass) {
return YAML.loadAs(dataStream, configClass);
}
}

View File

@@ -1,159 +0,0 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.config.loader;
import static org.geysermc.floodgate.util.MessageFormatter.format;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.geysermc.floodgate.util.Utils;
public class DefaultConfigHandler {
public void createDefaultConfig(String defaultConfigLocation, Path configPath) throws IOException {
List<String> configLines = loadDefaultConfig(defaultConfigLocation);
// writing the new config file
Files.write(configPath, configLines);
}
public List<String> loadDefaultConfig(String defaultConfigLocation)
throws IOException {
List<String> lines = Utils.readAllLines(defaultConfigLocation);
List<String> configLines = new ArrayList<>();
String parentConfig = null;
List<String> parentLines = null;
int lastInsertLine = -1;
int tempAddAfter = -1;
for (String line : lines) {
// >>(space) or >>|
if (line.startsWith(">>")) {
if (line.length() >= 3) {
// define parent file
if (line.charAt(2) == ' ') {
if (tempAddAfter != -1) {
throw new IllegalStateException(
"Cannot define new parent without closing the current section");
}
parentConfig = line.substring(3);
parentLines = null;
lastInsertLine = -1;
continue;
}
// define start / end of insert section
if (line.charAt(2) == '|') {
// end section
if (line.length() == 3) {
if (tempAddAfter == -1) {
throw new IllegalStateException("Cannot close an unclosed section");
}
lastInsertLine = tempAddAfter;
tempAddAfter = -1;
continue;
}
// start insert section
if (parentConfig == null) {
throw new IllegalStateException(
"Cannot start insert section without providing a parent");
}
if (tempAddAfter != -1) {
throw new IllegalStateException(
"Cannot start section with an unclosed section");
}
// note that addAfter starts counting from 1
int addAfter = Integer.parseInt(line.substring(4)) - 1;
if (lastInsertLine > -1 && addAfter < lastInsertLine) {
throw new IllegalStateException(format(
"Cannot add the same lines twice {} {}",
addAfter, lastInsertLine
));
}
// as you can see by this implementation
// we don't support parent files in parent files
if (lastInsertLine == -1) {
parentLines = Utils.readAllLines(parentConfig);
for (int i = 0; i <= addAfter; i++) {
configLines.add(parentLines.get(i));
}
} else {
for (int i = lastInsertLine; i <= addAfter; i++) {
configLines.add(parentLines.get(i));
}
}
tempAddAfter = addAfter;
continue;
}
if (line.charAt(2) == '*') {
if (parentConfig == null) {
throw new IllegalStateException(
"Cannot write rest of the parent without providing a parent");
}
if (tempAddAfter != -1) {
throw new IllegalStateException(
"Cannot write rest of the parent config while an insert section is still open");
}
if (lastInsertLine == -1) {
parentLines = Utils.readAllLines(parentConfig);
configLines.addAll(parentLines);
continue;
}
// the lastInsertLine has already been printed, so we won't print it twice
for (int i = lastInsertLine + 1; i < parentLines.size(); i++) {
configLines.add(parentLines.get(i));
}
continue;
}
throw new IllegalStateException(
"The use of >>" + line.charAt(2) + " is unknown");
}
throw new IllegalStateException("Unable do something with just >>");
}
// everything else: comments and key/value lines will be added
configLines.add(line);
}
return configLines;
}
}

View File

@@ -1,182 +0,0 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.config.updater;
import com.google.common.base.Ascii;
import com.google.inject.Inject;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.config.loader.DefaultConfigHandler;
public final class ConfigFileUpdater {
@Inject private FloodgateLogger logger;
@Inject private DefaultConfigHandler defaultConfigHandler;
/**
* Simple config file updater. Please note that all the keys should be unique and that this
* system wasn't made for complex configurations.
*
* @param configLocation the location of the Floodgate config
* @param currentVersion the key value map of the current config
* @param renames name changes introduced in this version. new (key) to old
* (value)
* @param defaultConfigLocation the location of the default Floodgate config
* @throws IOException if an I/O error occurs
*/
public void update(
Path configLocation,
Map<String, Object> currentVersion,
Map<String, String> renames,
String defaultConfigLocation)
throws IOException {
List<String> notFound = new ArrayList<>();
List<String> newConfig = defaultConfigHandler.loadDefaultConfig(defaultConfigLocation);
String spaces = "";
Map<String, Object> map = null;
String line;
for (int i = 0; i < newConfig.size(); i++) {
line = newConfig.get(i);
// we don't have to check comments or empty lines
if (line.isEmpty() || line.charAt(0) == '#') {
continue;
}
StringBuilder currentSpaces = new StringBuilder();
while (line.charAt(currentSpaces.length()) == Ascii.SPACE) {
currentSpaces.append(Ascii.SPACE);
}
// end of subcategory
if (!spaces.isEmpty() && currentSpaces.length() < spaces.length()) {
// we can assume this since we don't allow subcategories of subcategories
spaces = "";
map = null;
}
// ignore comments
if (line.charAt(currentSpaces.length()) == '#') {
continue;
}
int splitIndex = line.indexOf(':');
// if the line has a 'key: value' structure
if (splitIndex != -1) {
// start of a subcategory
if (line.length() == splitIndex + 1) {
if (currentSpaces.length() > 0) {
throw new IllegalStateException(
"Config too complex! I can't understand subcategories of a subcategory");
}
spaces = " ";
//todo allow rename of subcategory?
//noinspection unchecked
map = (Map<String, Object>) currentVersion.get(line.substring(0, splitIndex));
continue;
}
String name = line.substring(spaces.length(), splitIndex);
// don't change the config-version to the old value!
if (name.equals("config-version")) {
continue;
}
// allow multiple renames
String tempName;
String oldName = name;
do {
tempName = oldName;
oldName = renames.getOrDefault(oldName, oldName);
} while (!oldName.equals(tempName));
Object value;
if (map != null) {
value = map.get(oldName);
} else {
value = currentVersion.get(spaces + oldName);
}
// use default value if the key doesn't exist in the current version
if (value == null) {
notFound.add(name);
continue;
}
if (value instanceof String) {
String v = (String) value;
if (!v.startsWith("\"") || !v.endsWith("\"")) {
value = "\"" + value + "\"";
}
//todo this doesn't update {0} {1} to {} {} e.g.
}
logger.debug(name + " has been changed to " + value);
newConfig.set(i, spaces + name + ": " + value);
}
}
Files.deleteIfExists(configLocation.getParent().resolve("config-old.yml"));
Files.copy(configLocation, configLocation.getParent().resolve("config-old.yml"));
Files.write(configLocation, newConfig);
logger.info("Successfully updated the config file! " +
"Your old config has been moved to config-old.yml");
if (!notFound.isEmpty()) {
StringBuilder messageBuilder = new StringBuilder(
"Please note that the following keys we not found in the old config and " +
"are now using the default Floodgate config value. Missing/new keys: ");
boolean first = true;
for (String value : notFound) {
if (!first) {
messageBuilder.append(", ");
}
String renamed = renames.get(value);
if (renamed != null) {
messageBuilder.append(renamed).append(" to ");
}
messageBuilder.append(value);
first = false;
}
logger.info(messageBuilder.toString());
}
}
}

View File

@@ -1,122 +0,0 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.config.updater;
import static com.google.common.base.Preconditions.checkArgument;
import static org.geysermc.floodgate.util.MessageFormatter.format;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.config.loader.ConfigLoader;
import org.yaml.snakeyaml.Yaml;
@RequiredArgsConstructor
public final class ConfigUpdater {
private static final int CONFIG_VERSION = 2;
private final Path dataFolder;
private final ConfigFileUpdater fileUpdater;
private final FloodgateLogger logger;
public void update(ConfigLoader loader, String defaultConfigLocation) {
Path configLocation = dataFolder.resolve("config.yml");
Map<String, Object> config;
try (BufferedReader configReader = Files.newBufferedReader(configLocation)) {
config = new Yaml().load(configReader);
} catch (IOException exception) {
logger.error("Error while opening the config file", exception);
throw new RuntimeException("Failed to update config", exception);
}
// new name -> old name
Map<String, String> renames = new HashMap<>();
int version = 0; // pre-rewrite is the default config version
Object versionElement = config.get("config-version");
// only rewrite configs have a config-version
if (versionElement == null) {
logger.warn("We've detected a pre-rewrite config file, please note that Floodgate " +
"doesn't not work properly if you don't update your Floodgate key used on " +
"all your servers (including Geyser). We'll try to update your Floodgate " +
"config now and we'll also generate a new Floodgate key for you, but if " +
"you're running a network or if you're running a Spigot server with " +
"Geyser Standalone please update as you'll no longer be able to connect.");
renames.put("enabled", "enable"); //todo make dump system and add a boolean 'found-legacy-key' or something like that
renames.put("allowed", "allow-linking");
// relocate the old key so that they can restore it if it was a new key
Path keyFilePath = dataFolder.resolve((String) config.get("key-file-name"));
if (Files.exists(keyFilePath)) {
try {
Files.copy(keyFilePath, dataFolder.resolve("old-key.pem"));
} catch (IOException exception) {
throw new RuntimeException(
"Failed to relocate the old key to make place for a new key",
exception);
}
}
loader.generateKey(keyFilePath);
} else {
// get (and verify) the config version
checkArgument(
versionElement instanceof Integer,
"Config version should be an integer. Did someone mess with the config?"
);
version = (int) versionElement;
checkArgument(
version > 0 && version <= CONFIG_VERSION,
format("Config is newer then possible on this version! Expected {}, got {}",
CONFIG_VERSION, version));
}
// config is already up-to-date
if (version == CONFIG_VERSION) {
return;
}
if (version < 2) {
// renamed 'use-global-linking' to 'enable-global-linking'
// and added 'enable-own-linking'
renames.put("enable-global-linking", "use-global-linking");
}
try {
fileUpdater.update(configLocation, config, renames, defaultConfigLocation);
} catch (IOException exception) {
logger.error("Error while updating the config file", exception);
throw new RuntimeException("Failed to update config", exception);
}
}
}

View File

@@ -1,149 +0,0 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.platform.command;
import java.util.Collection;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.floodgate.player.UserAudience;
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
import org.geysermc.floodgate.util.Utils;
/**
* An interface used across all Floodgate platforms to simple stuff in commands like kicking players
* and sending player messages independent of the Floodgate platform implementation.
*/
public interface CommandUtil {
@NonNull UserAudience getAudience(final @NonNull Object source);
@Nullable UserAudience getAudienceByUuid(final @NonNull UUID uuid);
@NonNull UserAudience getOfflineAudienceByUuid(final @NonNull UUID uuid);
@Nullable UserAudience getAudienceByUsername(final @NonNull String username);
@NonNull UserAudience getOfflineAudienceByUsername(final @NonNull String username);
@NonNull Collection<String> getOnlineUsernames(final @NonNull PlayerType limitTo);
/**
* Checks if the given player has the given permission.
*
* @param player the player to check
* @param permission the permission to check
* @return true or false depending on if the player has the permission
*/
boolean hasPermission(Object player, String permission);
/**
* Get all online players with the given permission.
*
* @param permission the permission to check
* @return a list of online players that have the given permission
*/
Collection<Object> getOnlinePlayersWithPermission(String permission);
/**
* Send a message to the specified target, no matter what platform Floodgate is running on.
*
* @param target the player that should receive the message
* @param message the command message
* @param locale the locale of the player
* @param args the arguments
*/
void sendMessage(Object target, String locale, TranslatableMessage message, Object... args);
/**
* Sends a raw message to the specified target, no matter what platform Floodgate is running
* on.
*
* @param target the player that should receive the message
* @param message the message
*/
void sendMessage(Object target, String message);
/**
* Same as {@link CommandUtil#sendMessage(Object, String, TranslatableMessage, Object...)}
* except it kicks the player using the given message as the kick reason.
*
* @param player the player that should be kicked
* @param message the command message
* @param locale the locale of the player
* @param args the arguments
*/
void kickPlayer(Object player, String locale, TranslatableMessage message, Object... args);
/**
* Whitelist the given Bedrock player.
*
* @param xuid the xuid of the username to be whitelisted
* @param username the username to be whitelisted
* @return true if the player has been whitelisted, false if the player was already whitelisted.
* Defaults to false when this platform doesn't support whitelisting.
*/
default boolean whitelistPlayer(String xuid, String username) {
UUID uuid = Utils.getJavaUuid(xuid);
return whitelistPlayer(uuid, username);
}
/**
* Whitelist the given Bedrock player.
*
* @param uuid the UUID of the username to be whitelisted
* @param username the username to be whitelisted
* @return true if the player has been whitelisted, false if the player was already whitelisted.
* Defaults to false when this platform doesn't support whitelisting.
*/
default boolean whitelistPlayer(UUID uuid, String username) {
return false;
}
/**
* Removes the given Bedrock player from the whitelist.
*
* @param xuid the xuid of the username to be removed from the whitelist
* @param username the username to be removed from the whitelist
* @return true if the player has been removed from the whitelist, false if the player wasn't
* whitelisted. Defaults to false when this platform doesn't support whitelisting.
*/
default boolean removePlayerFromWhitelist(String xuid, String username) {
UUID uuid = Utils.getJavaUuid(xuid);
return removePlayerFromWhitelist(uuid, username);
}
/**
* Removes the given Bedrock player from the whitelist.
*
* @param uuid the UUID of the username to be removed from the whitelist
* @param username the username to be removed from the whitelist
* @return true if the player has been removed from the whitelist, false if the player wasn't
* whitelisted. Defaults to false when this platform doesn't support whitelisting.
*/
default boolean removePlayerFromWhitelist(UUID uuid, String username) {
return false;
}
}

View File

@@ -1,61 +0,0 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.platform.util;
import java.util.Collection;
import org.geysermc.floodgate.platform.command.CommandUtil;
import org.geysermc.floodgate.platform.command.TranslatableMessage;
public interface PlatformUtils {
/**
* Send a message to the specified player, no matter what platform Floodgate is running on.
*
* @param player the player to send the message to
* @param message the command message
* @param locale the locale of the player
* @param args the arguments
*/
void sendMessage(Object player, String locale, TranslatableMessage message, Object... args);
/**
* Same as {@link CommandUtil#sendMessage(Object, String, TranslatableMessage, Object...)} except it
* kicks the player.
*
* @param player the player to send the message to
* @param message the command message
* @param locale the locale of the player
* @param args the arguments
*/
void kickPlayer(Object player, String locale, TranslatableMessage message, Object... args);
Collection<String> getOnlineUsernames(PlayerType limitTo);
enum PlayerType {
ALL_PLAYERS,
ONLY_BEDROCK,
ONLY_JAVA
}
}

View File

@@ -1,76 +0,0 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.player;
import java.util.UUID;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.MessageType;
import net.kyori.adventure.identity.Identified;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.floodgate.platform.command.TranslatableMessage;
public interface UserAudience extends Identified, Identity, Audience {
@Override
@NonNull UUID uuid();
@NonNull String username();
@NonNull String locale();
@NonNull Object source();
boolean hasPermission(@NonNull final String permission);
@Override
void sendMessage(final @NonNull Identity source,
final @NonNull Component message,
final @NonNull MessageType type);
void sendMessage(TranslatableMessage message, Object... args);
default void sendMessage(String message) {
sendMessage(Component.text(message));
}
void disconnect(@NonNull final Component reason);
void disconnect(TranslatableMessage message, Object... args);
@Override
default @NonNull Identity identity() {
return this;
}
interface PlayerAudience extends UserAudience {
boolean online();
}
interface ConsoleAudience extends UserAudience {
}
}

31
core/build.gradle.kts Normal file
View File

@@ -0,0 +1,31 @@
import net.kyori.blossom.BlossomExtension
plugins {
id("net.kyori.blossom")
}
dependencies {
api(projects.api)
api("org.geysermc.configutils", "configutils", Versions.configUtilsVersion)
api("com.google.inject", "guice", Versions.guiceVersion)
api("com.nukkitx.fastutil", "fastutil-short-object-maps", Versions.fastutilVersion)
api("com.nukkitx.fastutil", "fastutil-int-object-maps", Versions.fastutilVersion)
api("org.java-websocket", "Java-WebSocket", Versions.javaWebsocketVersion)
api("cloud.commandframework", "cloud-core", Versions.cloudVersion)
api("org.yaml", "snakeyaml", Versions.snakeyamlVersion)
api("org.bstats", "bstats-base", Versions.bstatsVersion)
}
// present on all platforms
provided("io.netty", "netty-transport", Versions.nettyVersion)
provided("io.netty", "netty-codec", Versions.nettyVersion)
relocate("org.bstats")
configure<BlossomExtension> {
val constantsFile = "src/main/java/org/geysermc/floodgate/util/Constants.java"
replaceToken("\${floodgateVersion}", fullVersion(), constantsFile)
replaceToken("\${branch}", branchName(), constantsFile)
replaceToken("\${buildNumber}", buildNumber(), constantsFile)
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,15 +40,14 @@ import org.geysermc.floodgate.api.inject.PlatformInjector;
import org.geysermc.floodgate.api.link.PlayerLink;
import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.api.packet.PacketHandlers;
import org.geysermc.floodgate.config.ConfigLoader;
import org.geysermc.floodgate.config.FloodgateConfig;
import org.geysermc.floodgate.config.FloodgateConfigHolder;
import org.geysermc.floodgate.config.loader.ConfigLoader;
import org.geysermc.floodgate.link.PlayerLinkLoader;
import org.geysermc.floodgate.module.ConfigLoadedModule;
import org.geysermc.floodgate.module.PostInitializeModule;
import org.geysermc.floodgate.news.NewsChecker;
import org.geysermc.floodgate.util.FloodgateInfoHolder;
import org.geysermc.floodgate.util.GitProperties;
import org.geysermc.floodgate.util.Metrics;
import org.geysermc.floodgate.util.PrefixCheckTask;
public class FloodgatePlatform {
@@ -61,9 +60,6 @@ public class FloodgatePlatform {
private FloodgateConfig config;
private Injector guice;
@Inject
private GitProperties properties;
@Inject
public FloodgatePlatform(
FloodgateApi api,
@@ -105,9 +101,6 @@ public class FloodgatePlatform {
InstanceHolder.set(api, link, this.injector, packetHandlers, handshakeHandlers, KEY);
// for Geyser dump
FloodgateInfoHolder.setGitProperties(properties.getProperties());
guice.getInstance(NewsChecker.class).start();
}
@@ -131,6 +124,8 @@ public class FloodgatePlatform {
PrefixCheckTask.checkAndExecuteDelayed(config, logger);
guice.getInstance(Metrics.class);
return true;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -70,7 +70,7 @@ public class HandshakeDataImpl implements HandshakeData {
int usernameLength = Math.min(bedrockData.getUsername().length(), 16 - prefix.length());
javaUsername = prefix + bedrockData.getUsername().substring(0, usernameLength);
if (config.isReplaceSpaces()) {
javaUsername = javaUsername.replaceAll(" ", "_");
javaUsername = javaUsername.replace(" ", "_");
}
javaUniqueId = Utils.getJavaUuid(bedrockData.getXuid());

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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 org.geysermc.floodgate.api;
import java.nio.charset.StandardCharsets;
import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.config.FloodgateConfigHolder;
import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
@@ -37,8 +38,9 @@ public final class ProxyFloodgateApi extends SimpleFloodgateApi {
public ProxyFloodgateApi(
PluginMessageManager pluginMessageManager,
FloodgateConfigHolder configHolder,
FloodgateLogger logger,
FloodgateCipher cipher) {
super(pluginMessageManager, configHolder);
super(pluginMessageManager, configHolder, logger);
this.cipher = cipher;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,6 +25,8 @@
package org.geysermc.floodgate.api;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableSet;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -33,13 +35,14 @@ import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nullable;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import org.geysermc.cumulus.Form;
import org.geysermc.cumulus.util.FormBuilder;
import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.geysermc.floodgate.api.unsafe.Unsafe;
import org.geysermc.floodgate.config.FloodgateConfigHolder;
import org.geysermc.floodgate.player.FloodgatePlayerImpl;
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
import org.geysermc.floodgate.pluginmessage.channel.FormChannel;
import org.geysermc.floodgate.pluginmessage.channel.TransferChannel;
@@ -50,8 +53,14 @@ import org.geysermc.floodgate.util.Utils;
@RequiredArgsConstructor
public class SimpleFloodgateApi implements FloodgateApi {
private final Map<UUID, FloodgatePlayer> players = new HashMap<>();
private final Cache<UUID, FloodgatePlayer> pendingRemove =
CacheBuilder.newBuilder()
.expireAfterWrite(20, TimeUnit.SECONDS)
.build();
private final PluginMessageManager pluginMessageManager;
private final FloodgateConfigHolder configHolder;
private final FloodgateLogger logger;
@Override
public String getPlayerPrefix() {
@@ -76,10 +85,14 @@ public class SimpleFloodgateApi implements FloodgateApi {
@Override
public FloodgatePlayer getPlayer(UUID uuid) {
FloodgatePlayer selfPlayer = players.get(uuid);
if (selfPlayer != null) {
return selfPlayer;
}
// bedrock players are always stored by their xuid,
// so we return the instance if we know that the given uuid is a Floodgate uuid
if (selfPlayer != null || isFloodgateId(uuid)) {
return selfPlayer;
if (isFloodgateId(uuid)) {
return pendingRemove.getIfPresent(uuid);
}
// make it possible to find player by Java id (linked players)
@@ -88,7 +101,8 @@ public class SimpleFloodgateApi implements FloodgateApi {
return player;
}
}
return null;
// and don't forget the pending remove linked players
return getPendingRemovePlayer(uuid);
}
@Override
@@ -152,67 +166,48 @@ public class SimpleFloodgateApi implements FloodgateApi {
});
}
public FloodgatePlayer addPlayer(UUID uuid, FloodgatePlayer player) {
return players.put(uuid, player);
@Override
public final Unsafe unsafe() {
String callerClass = Thread.currentThread().getStackTrace()[2].getClassName();
logger.warn("A plugin is trying to access an unsafe part of the Floodgate api!" +
" The use of this api can result in client crashes if used incorrectly." +
" Caller: " + callerClass);
return new UnsafeFloodgateApi(pluginMessageManager);
}
public FloodgatePlayer addPlayer(FloodgatePlayer player) {
// Bedrock players are always stored by their xuid
return players.put(player.getJavaUniqueId(), player);
}
/**
* Removes a player (should only be used internally)
*
* @param onlineId The UUID of the online player
* @param removeLogin true if it should remove a sessions who is still logging in
* @return the FloodgatePlayer the player was logged in with
* This method is invoked when the player is no longer on the server, but the related platform-
* dependant event hasn't fired yet
*/
@Nullable
public FloodgatePlayer removePlayer(UUID onlineId, boolean removeLogin) {
FloodgatePlayer selfPlayer = players.get(onlineId);
// the player is a non-linked player or a linked player but somehow someone tried to
// remove the player by his xuid, we have to find out
if (selfPlayer != null) {
// we don't allow them to remove a player by his xuid
// because a linked player is never registered by his linked java uuid
if (selfPlayer.getLinkedPlayer() != null) {
return null;
public boolean setPendingRemove(FloodgatePlayer player) {
pendingRemove.put(player.getJavaUniqueId(), player);
return players.remove(player.getJavaUniqueId(), player);
}
// removeLogin logic
if (!canRemove(selfPlayer, removeLogin)) {
return null;
public void playerRemoved(UUID correctUuid) {
// we can remove the player directly if it is a Floodgate UUID.
// since it's stored by their Floodgate UUID
if (isFloodgateId(correctUuid)) {
pendingRemove.invalidate(correctUuid);
return;
}
FloodgatePlayer linkedPlayer = getPendingRemovePlayer(correctUuid);
if (linkedPlayer != null) {
pendingRemove.invalidate(linkedPlayer.getJavaUniqueId());
}
}
// passed the test
players.remove(onlineId);
// was the account linked?
return selfPlayer;
}
// we still want to be able to remove a linked-player by his linked java uuid
for (FloodgatePlayer player : players.values()) {
if (canRemove(player, removeLogin) && player.getCorrectUniqueId().equals(onlineId)) {
players.remove(player.getJavaUniqueId());
private FloodgatePlayer getPendingRemovePlayer(UUID correctUuid) {
for (FloodgatePlayer player : pendingRemove.asMap().values()) {
if (player.getCorrectUniqueId().equals(correctUuid)) {
return player;
}
}
return null;
}
protected boolean canRemove(FloodgatePlayer player, boolean removeLogin) {
FloodgatePlayerImpl impl = player.as(FloodgatePlayerImpl.class);
return impl.isLogin() && removeLogin || !impl.isLogin() && !removeLogin;
}
/**
* Equivalant of {@link #removePlayer(UUID, boolean)} but with removeLogin = false.
*/
public FloodgatePlayer removePlayer(UUID onlineId) {
return removePlayer(onlineId, false);
}
/**
* Equivalent of {@link #removePlayer(UUID, boolean)} except that it removes a FloodgatePlayer
* instance directly.
*/
public boolean removePlayer(FloodgatePlayer player) {
return players.remove(player.getJavaUniqueId(), player);
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.api;
import java.util.UUID;
import org.geysermc.floodgate.api.unsafe.Unsafe;
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
import org.geysermc.floodgate.pluginmessage.channel.PacketChannel;
public final class UnsafeFloodgateApi implements Unsafe {
private final PacketChannel packetChannel;
UnsafeFloodgateApi(PluginMessageManager pluginMessageManager) {
StackTraceElement element = Thread.currentThread().getStackTrace()[2];
if (!SimpleFloodgateApi.class.getName().equals(element.getClassName())) {
throw new IllegalStateException("Use the Floodgate api to get an instance");
}
packetChannel = pluginMessageManager.getChannel(PacketChannel.class);
}
@Override
public void sendPacket(UUID bedrockPlayer, int packetId, byte[] packetData) {
byte[] fullData = new byte[packetData.length + 1];
fullData[0] = (byte) packetId;
System.arraycopy(packetData, 0, fullData, 1, packetData.length);
packetChannel.sendPacket(bedrockPlayer, fullData, this);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,20 +35,20 @@ import cloud.commandframework.context.CommandContext;
import com.google.inject.Inject;
import lombok.Getter;
import lombok.NoArgsConstructor;
import net.kyori.adventure.text.Component;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.link.LinkRequestResult;
import org.geysermc.floodgate.api.link.PlayerLink;
import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.command.util.Permission;
import org.geysermc.floodgate.config.FloodgateConfig;
import org.geysermc.floodgate.link.GlobalPlayerLinking;
import org.geysermc.floodgate.platform.command.FloodgateCommand;
import org.geysermc.floodgate.platform.command.TranslatableMessage;
import org.geysermc.floodgate.player.UserAudience;
import org.geysermc.floodgate.player.UserAudience.PlayerAudience;
import org.geysermc.floodgate.player.UserAudienceArgument;
import org.geysermc.floodgate.player.audience.ProfileAudience;
import org.geysermc.floodgate.player.audience.ProfileAudienceArgument;
import org.geysermc.floodgate.util.Constants;
import org.geysermc.floodgate.util.Permissions;
@NoArgsConstructor
public final class LinkAccountCommand implements FloodgateCommand {
@@ -60,8 +60,8 @@ public final class LinkAccountCommand implements FloodgateCommand {
return commandManager.commandBuilder("linkaccount",
ArgumentDescription.of("Link your Java account with your Bedrock account"))
.senderType(PlayerAudience.class)
.permission(Permissions.COMMAND_LINK.get())
.argument(UserAudienceArgument.of("player", true))
.permission(Permission.COMMAND_LINK.get())
.argument(ProfileAudienceArgument.of("player", true))
.argument(StringArgument.optional("code"))
.handler(this::execute)
.build();
@@ -125,7 +125,7 @@ public final class LinkAccountCommand implements FloodgateCommand {
sender.disconnect(Message.LINK_REQUEST_COMPLETED, targetName);
break;
default:
sender.disconnect(Component.text("Invalid account linking result"));
sender.disconnect("Invalid account linking result");
break;
}
});
@@ -137,7 +137,7 @@ public final class LinkAccountCommand implements FloodgateCommand {
return;
}
UserAudience targetUser = context.get("player");
ProfileAudience targetUser = context.get("player");
String targetName = targetUser.username();
link.createLinkRequest(sender.uuid(), sender.username(), targetName)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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 org.geysermc.floodgate.command;
import cloud.commandframework.Command;
import cloud.commandframework.CommandManager;
import cloud.commandframework.context.CommandContext;
import net.kyori.adventure.text.Component;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.config.FloodgateConfig;
import org.geysermc.floodgate.platform.command.FloodgateCommand;
@@ -47,7 +46,7 @@ public class TestCommand implements FloodgateCommand {
@Override
public void execute(CommandContext<UserAudience> context) {
int players = FloodgateApi.getInstance().getPlayers().size();
context.getSender().sendMessage(Component.text(players));
context.getSender().sendMessage(String.valueOf(players));
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,7 +43,7 @@ import org.geysermc.floodgate.platform.command.TranslatableMessage;
import org.geysermc.floodgate.player.UserAudience;
import org.geysermc.floodgate.player.UserAudience.PlayerAudience;
import org.geysermc.floodgate.util.Constants;
import org.geysermc.floodgate.util.Permissions;
import org.geysermc.floodgate.command.util.Permission;
@NoArgsConstructor
public final class UnlinkAccountCommand implements FloodgateCommand {
@@ -54,7 +54,7 @@ public final class UnlinkAccountCommand implements FloodgateCommand {
return commandManager.commandBuilder("unlinkaccount",
ArgumentDescription.of("Unlink your Java account from your Bedrock account"))
.senderType(PlayerAudience.class)
.permission(Permissions.COMMAND_UNLINK.get())
.permission(Permission.COMMAND_UNLINK.get())
.handler(this::execute)
.build();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -38,17 +38,18 @@ import java.util.UUID;
import lombok.Getter;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.command.util.Permission;
import org.geysermc.floodgate.config.FloodgateConfig;
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
import org.geysermc.floodgate.platform.command.CommandUtil;
import org.geysermc.floodgate.platform.command.FloodgateCommand;
import org.geysermc.floodgate.platform.command.TranslatableMessage;
import org.geysermc.floodgate.platform.util.PlayerType;
import org.geysermc.floodgate.player.UserAudience;
import org.geysermc.floodgate.player.UserAudienceArgument;
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
import org.geysermc.floodgate.player.audience.ProfileAudience;
import org.geysermc.floodgate.player.audience.ProfileAudienceArgument;
import org.geysermc.floodgate.util.Constants;
import org.geysermc.floodgate.util.HttpUtils;
import org.geysermc.floodgate.util.Permissions;
public class WhitelistCommand implements FloodgateCommand {
@Inject private FloodgateConfig config;
@@ -58,25 +59,25 @@ public class WhitelistCommand implements FloodgateCommand {
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
Command.Builder<UserAudience> builder = commandManager.commandBuilder("fwhitelist",
ArgumentDescription.of("Easy way to whitelist Bedrock players"))
.permission(Permissions.COMMAND_WHITELIST.get());
.permission(Permission.COMMAND_WHITELIST.get());
commandManager.command(builder
.literal("add", "a")
.argument(UserAudienceArgument.of("player", true, true, PlayerType.ONLY_BEDROCK))
.argument(ProfileAudienceArgument.of("player", true, true, PlayerType.ONLY_BEDROCK))
.handler(context -> performCommand(context, true)));
return builder
.literal("remove", "r")
.argument(UserAudienceArgument.of("player", true, true, PlayerType.ONLY_BEDROCK))
.argument(ProfileAudienceArgument.of("player", true, true, PlayerType.ONLY_BEDROCK))
.handler(context -> performCommand(context, false))
.build();
}
public void performCommand(CommandContext<UserAudience> context, boolean add) {
UserAudience sender = context.getSender();
UserAudience player = context.get("player");
UUID uuid = player.uuid();
String name = player.username();
ProfileAudience profile = context.get("player");
UUID uuid = profile.uuid();
String name = profile.username();
if (name == null && uuid == null) {
sender.sendMessage(Message.UNEXPECTED_ERROR);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,9 +35,9 @@ import cloud.commandframework.context.CommandContext;
import java.util.Locale;
import java.util.function.Consumer;
import lombok.RequiredArgsConstructor;
import org.geysermc.floodgate.command.util.Permission;
import org.geysermc.floodgate.platform.command.FloodgateCommand;
import org.geysermc.floodgate.player.UserAudience;
import org.geysermc.floodgate.util.Permissions;
public final class MainCommand implements FloodgateCommand {
@Override
@@ -46,12 +46,13 @@ public final class MainCommand implements FloodgateCommand {
"floodgate",
ArgumentDescription.of("A set of Floodgate related actions in one command"))
.senderType(UserAudience.class)
.permission(Permissions.COMMAND_MAIN.get())
.permission(Permission.COMMAND_MAIN.get())
.handler(this::execute);
for (SubCommand subCommand : SubCommand.VALUES) {
commandManager.command(builder
.literal(subCommand.name().toLowerCase(Locale.ROOT), subCommand.description)
.permission(subCommand.permission.get())
.handler(subCommand.executor::accept)
);
}
@@ -65,11 +66,13 @@ public final class MainCommand implements FloodgateCommand {
StringBuilder helpMessage = new StringBuilder("Available subcommands are:\n");
for (SubCommand subCommand : SubCommand.VALUES) {
if (context.getSender().hasPermission(subCommand.permission.get())) {
helpMessage.append('\n').append(COLOR_CHAR).append('b')
.append(subCommand.name().toLowerCase(Locale.ROOT))
.append(COLOR_CHAR).append("f - ").append(COLOR_CHAR).append('7')
.append(subCommand.description);
}
}
context.getSender().sendMessage(helpMessage.toString());
}
@@ -77,11 +80,12 @@ public final class MainCommand implements FloodgateCommand {
@RequiredArgsConstructor
enum SubCommand {
FIREWALL("Check if your outgoing firewall allows Floodgate to work properly",
FirewallCheckSubcommand::executeFirewall);
Permission.COMMAND_MAIN_FIREWALL, FirewallCheckSubcommand::executeFirewall);
static final SubCommand[] VALUES = values();
final String description;
final Permission permission;
final Consumer<CommandContext<UserAudience>> executor;
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.command.util;
import static org.geysermc.floodgate.command.util.PermissionDefault.OP;
import static org.geysermc.floodgate.command.util.PermissionDefault.TRUE;
public enum Permission {
COMMAND_MAIN("floodgate.command.floodgate", TRUE),
COMMAND_MAIN_FIREWALL(COMMAND_MAIN, "firewall", OP),
COMMAND_LINK("floodgate.command.linkaccount", TRUE),
COMMAND_UNLINK("floodgate.command.unlinkaccount", TRUE),
COMMAND_WHITELIST("floodgate.command.fwhitelist", OP),
NEWS_RECEIVE("floodgate.news.receive", OP);
private final String permission;
private final PermissionDefault defaultValue;
Permission(String permission, PermissionDefault defaultValue) {
this.permission = permission;
this.defaultValue = defaultValue;
}
Permission(Permission parent, String child, PermissionDefault defaultValue) {
this(parent.get() + "." + child, defaultValue);
}
public String get() {
return permission;
}
public PermissionDefault defaultValue() {
return defaultValue;
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.command.util;
public enum PermissionDefault {
TRUE, FALSE, OP, NOT_OP
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,26 +23,27 @@
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.config.loader;
package org.geysermc.floodgate.config;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.Key;
import java.util.UUID;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.geysermc.configutils.ConfigUtilities;
import org.geysermc.configutils.file.codec.PathFileCodec;
import org.geysermc.configutils.file.template.ResourceTemplateReader;
import org.geysermc.configutils.updater.change.Changes;
import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.config.FloodgateConfig;
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
import org.geysermc.floodgate.config.updater.ConfigUpdater;
import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.floodgate.crypto.KeyProducer;
@Getter
@RequiredArgsConstructor
public final class ConfigLoader {
private final Path dataFolder;
private final Class<? extends FloodgateConfig> configClass;
private final DefaultConfigHandler configCreator;
private final ConfigUpdater updater;
private final KeyProducer keyProducer;
private final FloodgateCipher cipher;
@@ -51,61 +52,42 @@ public final class ConfigLoader {
@SuppressWarnings("unchecked")
public <T extends FloodgateConfig> T load() {
Path configPath = dataFolder.resolve("config.yml");
String defaultConfigName = "config.yml";
boolean proxy = ProxyFloodgateConfig.class.isAssignableFrom(configClass);
if (proxy) {
defaultConfigName = "proxy-" + defaultConfigName;
String templateFile = "config.yml";
if (ProxyFloodgateConfig.class.isAssignableFrom(configClass)) {
templateFile = "proxy-" + templateFile;
}
boolean newConfig = !Files.exists(configPath);
if (newConfig) {
try {
configCreator.createDefaultConfig(defaultConfigName, configPath);
} catch (Exception exception) {
logger.error("Error while creating config", exception);
}
}
//todo old Floodgate logged a message when version = 0 and it generated a new key.
// Might be nice to allow you to run a function for a specific version.
T configInstance;
try {
// check and update if the config is outdated
if (!newConfig) {
updater.update(this, defaultConfigName);
}
// it would also be nice to have sections in versionBuilder so that you don't have to
// provide the path all the time
FloodgateConfig config = ConfigInitializer.initializeFrom(
Files.newInputStream(configPath), configClass);
ConfigUtilities utilities =
ConfigUtilities.builder()
.fileCodec(PathFileCodec.of(dataFolder))
.configFile("config.yml")
.templateReader(ResourceTemplateReader.of(getClass()))
.template(templateFile)
.changes(Changes.builder()
.version(1, Changes.versionBuilder()
.keyRenamed("player-link.enable", "player-link.enabled")
.keyRenamed("player-link.allow-linking", "player-link.allowed"))
.version(2, Changes.versionBuilder()
.keyRenamed("player-link.use-global-linking", "player-link.enable-global-linking"))
.build())
.definePlaceholder("metrics.uuid", UUID::randomUUID)
.postInitializeCallbackArgument(this)
.build();
try {
configInstance = (T) config;
} catch (ClassCastException exception) {
logger.error("Failed to cast config file to required class.", exception);
throw new RuntimeException(exception);
}
} catch (Exception exception) {
logger.error("Error while loading config", exception);
return (T) utilities.executeOn(configClass);
} catch (Throwable throwable) {
throw new RuntimeException(
"Failed to load the config! Try to delete the config file", exception);
"Failed to load the config! Try to delete the config file if this error persists",
throwable
);
}
Path keyPath = dataFolder.resolve(configInstance.getKeyFileName());
// don't assume that the key always exists with the existence of a config
if (!Files.exists(keyPath)) {
generateKey(keyPath);
}
try {
Key key = keyProducer.produceFrom(keyPath);
cipher.init(key);
configInstance.setKey(key);
} catch (IOException exception) {
logger.error("Error while reading the key", exception);
throw new RuntimeException("Failed to read the key!", exception);
}
return configInstance;
}
public void generateKey(Path keyPath) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,15 +25,20 @@
package org.geysermc.floodgate.config;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.Key;
import lombok.Getter;
import org.geysermc.configutils.loader.callback.CallbackResult;
import org.geysermc.configutils.loader.callback.GenericPostInitializeCallback;
/**
* The global Floodgate configuration file used in every platform. Some platforms have their own
* addition to the global configuration like {@link ProxyFloodgateConfig} for the proxies.
*/
@Getter
public class FloodgateConfig {
public class FloodgateConfig implements GenericPostInitializeCallback<ConfigLoader> {
private String keyFileName;
private String usernamePrefix;
private boolean replaceSpaces;
@@ -42,22 +47,36 @@ public class FloodgateConfig {
private DisconnectMessages disconnect;
private PlayerLinkConfig playerLink;
private MetricsConfig metrics;
private boolean debug;
private int configVersion;
private Key key;
public void setKey(Key key) {
if (this.key == null) {
this.key = key;
}
}
public boolean isProxy() {
return this instanceof ProxyFloodgateConfig;
}
@Override
public CallbackResult postInitialize(ConfigLoader loader) {
Path keyPath = loader.getDataFolder().resolve(getKeyFileName());
// don't assume that the key always exists with the existence of a config
if (!Files.exists(keyPath)) {
loader.generateKey(keyPath);
}
try {
Key floodgateKey = loader.getKeyProducer().produceFrom(keyPath);
loader.getCipher().init(floodgateKey);
key = floodgateKey;
} catch (IOException exception) {
return CallbackResult.failed(exception.getMessage());
}
return CallbackResult.ok();
}
@Getter
public static class DisconnectMessages {
private String invalidKey;
@@ -68,10 +87,16 @@ public class FloodgateConfig {
public static class PlayerLinkConfig {
private boolean enabled;
private boolean requireLink;
private boolean enableOwnLinking = false;
private boolean enableOwnLinking;
private boolean allowed;
private long linkCodeTimeout;
private String type;
private boolean enableGlobalLinking;
}
@Getter
public static class MetricsConfig {
private boolean enabled;
private String uuid;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -77,7 +77,7 @@ public abstract class CommonPlatformInjector implements PlatformInjector {
}
/**
* Method to loop throguh all the addons and call {@link InjectorAddon#onChannelClosed(Channel)}
* Method to loop through all the addons and call {@link InjectorAddon#onChannelClosed(Channel)}
* if {@link InjectorAddon#shouldInject()}
*
* @param channel the channel that was injected

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* 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,5 +1,5 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

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