Compare commits

..
1 Commits
Author SHA1 Message Date
Luck b32e9040c1 Folia support 2025-07-21 22:33:47 +01:00
99 changed files with 2338 additions and 1003 deletions

No files matched your search

-1
View File
@@ -3,4 +3,3 @@
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf
.gitea/CODEOWNERS linguist-detectable=false
-3
View File
@@ -1,3 +0,0 @@
# Pull requests request review from the eligible staff team(s).
# One approval from either an Admin or Developer satisfies branch protection.
* @trueog/Admins @trueog/Developers
+2
View File
@@ -0,0 +1,2 @@
github: lucko
patreon: luckdev
+63
View File
@@ -0,0 +1,63 @@
name: 🐛 ​ Bug report
description: Report an issue or problem with the way LuckPerms is functioning.
labels: ["type: issue"]
body:
- type: markdown
attributes:
value: "Before going any further, please check to see if your problem is fixed by updating to a newer version. The latest development builds can be obtained from https://luckperms.net/download"
- type: textarea
id: description
attributes:
label: Description
description: Please provide a short description of the issue in the space below.
placeholder: Description goes here!
validations:
required: true
- type: textarea
id: reproduction-steps
attributes:
label: Reproduction Steps
description: Please provide a clear list of steps we should follow in order to reproduce your issue in the space below.
placeholder: List reproduction steps here, please!
validations:
required: true
- type: textarea
id: expected-behaviour
attributes:
label: Expected Behaviour
description: Please provide a description of what you expected to happen.
placeholder: Describe what you expected to happen here.
validations:
required: true
- type: input
id: server-info
attributes:
label: Server Details
description: Please provide a description of the server details, including type and specific version number.
placeholder: 'git-Paper-124 (MC: 1.17.1)'
validations:
required: true
- type: input
id: luckperms-version
attributes:
label: LuckPerms Version
description: Please provide the specific, precise version number of LuckPerms you are using to reproduce this bug.
placeholder: v5.3.70
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs and Configs
description: If you think it would be helpful, please also include a pastebin of any relevant config files or log output. You should use https://gist.github.com/ to upload, then include the link below.
placeholder: https://gist.github.com/HelpfulBugReporter/ThisIsAVeryUsefulLogOutput
validations:
required: false
- type: textarea
id: extra-info
attributes:
label: Extra Details
description: Please include any other relevant details in the space below.
placeholder: I was able to reproduce this only at the end of a rainbow.
validations:
required: false
+5
View File
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: 💬 ​ Ask a question
url: https://discord.gg/luckperms
about: We use Discord to provide support for the project. If you have a question, need help, or aren't sure if you've found a bug or not, please come and talk to us there!
+31
View File
@@ -0,0 +1,31 @@
name: 💡 ​ Suggestion
description: Suggest an idea for an improvement or change to LuckPerms.
labels: ["type: suggestion"]
body:
- type: markdown
attributes:
value: "Before going any further, please check to see if your suggestion has already been added by checking the [wiki](https://luckperms.net/wiki/Home). The latest development builds can be obtained from https://luckperms.net/download"
- type: textarea
id: description
attributes:
label: Description
description: Please provide a short description of your suggestion in the space below.
placeholder: Hello, perhaps you should...
validations:
required: true
- type: textarea
id: proposed-behaviour
attributes:
label: Proposed Behaviour
description: Please provide a short explanation of how the feature should work / be changed, and how this will affect the project.
placeholder: It would...
validations:
required: true
- type: textarea
id: extra-info
attributes:
label: Extra Details
description: Please include any other relevant details in the space below.
placeholder: I think this should only function at the end of a rainbow.
validations:
required: false
+128
View File
@@ -0,0 +1,128 @@
name: Build Gradle and Publish Docker image
on:
push:
branches:
- 'master'
tags:
- 'v*'
pull_request:
branches:
- 'master'
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-gradle:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Run build and tests with Gradle wrapper
run: ./gradlew test build -PdockerTests
- name: Publish test report
uses: mikepenz/action-junit-report@v5
if: success() || failure()
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
annotate_notice: true
detailed_summary: true
- name: Upload all artifacts
uses: actions/upload-artifact@v4
with:
name: jars
path: |
bukkit/loader/build/libs/LuckPerms-Bukkit-*.jar
bukkit-legacy/loader/build/libs/LuckPerms-Bukkit-Legacy-*.jar
bungee/loader/build/libs/LuckPerms-Bungee-*.jar
sponge/loader/build/libs/LuckPerms-Sponge-*.jar
nukkit/loader/build/libs/LuckPerms-Nukkit-*.jar
velocity/build/libs/LuckPerms-Velocity-*.jar
fabric/build/libs/LuckPerms-Fabric-*.jar
forge/loader/build/libs/LuckPerms-Forge-*.jar
standalone/loader/build/libs/LuckPerms-Standalone-*.jar
- name: Upload standalone artifact
uses: actions/upload-artifact@v4
with:
name: standalone-binary
path: standalone/loader/build/libs/LuckPerms-Standalone-*.jar
build-docker:
needs: build-gradle
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Retrieve saved standalone jar artifact
uses: actions/download-artifact@v4
with:
name: standalone-binary
path: standalone/docker/
- name: Remove version number from jar artifact name
run: mv standalone/docker/LuckPerms-Standalone-*.jar standalone/docker/luckperms-standalone.jar
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Determine the LuckPerms version
run: |
echo "luckperms_version=$(git describe --tags | awk -F "-" '{print $1 "." $2}')" >> "$GITHUB_ENV"
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: |
latest=${{ github.ref == 'refs/heads/master' }}
tags: |
type=schedule
type=ref,event=branch
type=ref,event=tag
type=ref,event=pr
type=raw,enable=${{ github.ref == 'refs/heads/master' }},value=${{ env.luckperms_version }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: standalone/docker/
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+26
View File
@@ -0,0 +1,26 @@
### :speech_balloon: Looking for support?
Details about support for the project can be found [here, on the Wiki Homepage](https://luckperms.net/wiki/Home#support).
### :bug: Reporting bugs?
Before reporting a bug or issue, please make sure that the issue is actually being caused by or related to LuckPerms. We get a lot of reports which are caused by other software - please double check!
If you're unsure, feel free to ask using the above resources BEFORE making a report.
Bugs or issues should be reported using the [GitHub Issues tab](https://github.com/LuckPerms/LuckPerms/issues).
### :pencil: Want to contribute code?
#### Pull Requests
If you make any changes or improvements to the plugin which you think would be beneficial to others, please consider making a pull request to merge your changes back into the upstream project. (especially if your changes are bug fixes!)
LuckPerms loosely follows the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html). Generally, try to copy the style of code found in the class you're editing.
If you're considering submitting a substantial pull request, please open an issue so we can discuss the change before starting work on the contribution. Most pull requests are happily accepted, but larger changes may have an impact on the maintainability of the project, and require more consideration.
#### Project Layout
The project is split up into a few separate modules.
* **API** - The public, semantically versioned API used by other plugins wishing to integrate with and retrieve data from LuckPerms. This module (for the most part) does not contain any implementation itself, and is provided by the plugin.
* **Common** - The common module contains most of the code which implements the respective LuckPerms plugins. This abstract module reduces duplicated code throughout the project.
* **Bukkit, BungeeCord, Fabric, Forge, Nukkit, Sponge & Velocity** - Each use the common module to implement plugins on the respective server platforms.
+109
View File
@@ -0,0 +1,109 @@
group = 'net.luckperms'
project.version = '5.5'
sourceCompatibility = 1.8
targetCompatibility = 1.8
jar {
manifest {
attributes('Automatic-Module-Name': 'net.luckperms.api')
}
}
dependencies {
compileOnly 'org.checkerframework:checker-qual:3.49.3'
compileOnly 'org.jetbrains:annotations:26.0.2'
}
// Only used occasionally for deployment - not needed for normal builds.
/*
if (project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword')) {
apply plugin: 'signing'
javadoc {
title = 'LuckPerms API (v' + project.ext.apiVersion + ')'
options.overview = 'javadoc/overview.html'
options.encoding = 'UTF-8'
options.charSet = 'UTF-8'
options.links(
'https://checkerframework.org/api/',
'https://javadoc.io/static/org.jetbrains/annotations/26.0.2/'
)
options.addStringOption('Xdoclint:none', '-quiet')
options.addStringOption('-since', '5.0,5.1,5.2,5.3,5.4,5.5')
if (JavaVersion.current() > JavaVersion.VERSION_1_8) {
options.links.add('https://docs.oracle.com/en/java/javase/21/docs/api/')
} else {
options.links.add('https://docs.oracle.com/javase/8/docs/api/')
}
}
java {
withJavadocJar()
withSourcesJar()
}
publishing {
repositories {
maven {
def releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
def snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots/'
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
credentials {
username sonatypeUsername
password sonatypePassword
}
}
}
publications {
mavenJava(MavenPublication) {
artifactId = 'api'
from components.java
pom {
name = 'LuckPerms API'
description = 'A permissions manager for Minecraft servers.'
url = 'https://luckperms.net'
licenses {
license {
name = 'MIT'
url = 'https://opensource.org/licenses/MIT'
}
}
developers {
developer {
id = 'lucko'
name = 'Luck'
url = 'https://lucko.me'
email = 'git@lucko.me'
}
}
scm {
connection = 'scm:git:https://github.com/LuckPerms/LuckPerms.git'
developerConnection = 'scm:git:git@github.com:LuckPerms/LuckPerms.git'
url = 'https://github.com/LuckPerms/LuckPerms'
}
issueManagement {
system = 'GitHub'
url = 'https://github.com/LuckPerms/LuckPerms/issues'
}
}
}
}
}
signing {
useGpgCmd()
sign publishing.publications.mavenJava
required = true
}
}
*/
+81
View File
@@ -0,0 +1,81 @@
plugins {
alias(libs.plugins.licenser) apply false
}
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
defaultTasks 'licenseFormat', 'build'
subprojects {
apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: 'org.cadixdev.licenser'
group = 'me.lucko.luckperms'
version = '5.5-SNAPSHOT'
sourceCompatibility = 11
targetCompatibility = 11
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
}
tasks.withType(Test).configureEach {
testLogging {
events = [TestLogEvent.PASSED, TestLogEvent.FAILED, TestLogEvent.SKIPPED]
exceptionFormat = TestExceptionFormat.FULL
showExceptions = true
showCauses = true
showStackTraces = true
}
}
jar {
from '../LICENSE.txt'
}
def determinePatchVersion = {
// get the name of the last tag
def tagInfo = new ByteArrayOutputStream()
exec {
commandLine 'git', 'describe', '--tags'
standardOutput = tagInfo
}
tagInfo = tagInfo.toString()
if (!tagInfo.contains('-')) {
return 0
}
return tagInfo.split("-")[1]
}
project.ext.majorVersion = '5'
project.ext.minorVersion = '5'
project.ext.patchVersion = determinePatchVersion()
project.ext.apiVersion = project.ext.majorVersion + '.' + project.ext.minorVersion
project.ext.fullVersion = project.ext.apiVersion + '.' + project.ext.patchVersion
license {
header = rootProject.file('HEADER.txt')
include '**/*.java'
newLine = true
}
repositories {
// Fix issue with lwjgl-freetype not being found on macOS / ForgeGradle issue
//
// Could not resolve all files for configuration ':_compileJava_1'.
// Could not find lwjgl-freetype-3.3.3-natives-macos-patch.jar (org.lwjgl:lwjgl-freetype:3.3.3).
maven {
url "https://libraries.minecraft.net"
content {
includeModule("org.lwjgl", "lwjgl-freetype")
}
}
mavenCentral()
maven { url 'https://repo.lucko.me/' }
maven { url 'https://libraries.minecraft.net/' }
}
}
-348
View File
@@ -1,348 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.kotlin.dsl.provideDelegate
/* ------------------------------ Plugins ------------------------------ */
plugins {
id("java") // Import Java plugin.
id("java-library") // Import Java Library plugin.
id("com.diffplug.spotless") version "7.0.4" // Import Spotless plugin.
id("com.gradleup.shadow") version "8.3.8" // Import Shadow plugin.
id("checkstyle") // Import Checkstyle plugin.
eclipse // Import Eclipse plugin.
kotlin("jvm") version "2.1.21" // Import Kotlin JVM plugin.
}
extra["kotlinAttribute"] = Attribute.of("kotlin-tag", Boolean::class.javaObjectType)
val kotlinAttribute: Attribute<Boolean> by rootProject.extra
/* --------------------------- JDK / Kotlin ---------------------------- */
java {
sourceCompatibility = JavaVersion.VERSION_17 // Compile with JDK 17 compatibility.
toolchain { // Select Java toolchain.
languageVersion.set(JavaLanguageVersion.of(17)) // Use JDK 17.
vendor.set(JvmVendorSpec.GRAAL_VM) // Use GraalVM CE.
}
}
kotlin { jvmToolchain(17) }
/* ----------------------------- Metadata ------------------------------ */
group = "me.lucko.luckperms" // Declare bundle identifier.
version = "5.5.0-SNAPSHOT" // Declare plugin version (will be in .jar).
val apiVersion = "1.19" // Declare minecraft server target version.
/* ----------------------------- Resources ----------------------------- */
tasks.named<ProcessResources>("processResources") {
val props = mapOf("version" to version, "apiVersion" to apiVersion)
inputs.properties(props) // Indicates to rerun if version changes.
filesMatching("plugin.yml") { expand(props) }
from("LICENSE") { into("/") } // Bundle licenses into jarfiles.
}
/* ---------------------------- Repos ---------------------------------- */
repositories {
// Fix issue with lwjgl-freetype not being found on macOS / ForgeGradle issue
maven("https://libraries.minecraft.net") { content { includeModule("org.lwjgl", "lwjgl-freetype") } }
mavenCentral()
maven { url = uri("https://repo.lucko.me/") }
maven { url = uri("https://libraries.minecraft.net/") }
maven { url = uri("https://repo.papermc.io/repository/maven-public/") }
maven { url = uri("file://${System.getProperty("user.home")}/.m2/repository") }
System.getProperty("SELF_MAVEN_LOCAL_REPO")?.let {
val dir = file(it)
if (dir.isDirectory) {
println("Using SELF_MAVEN_LOCAL_REPO at: $it")
maven { url = uri("file://${dir.absolutePath}") }
} else {
mavenLocal()
}
}
}
/* ---------------------- Java project deps ---------------------------- */
dependencies {
// Root project carries no direct compile deps; subprojects declare their own.
}
/* ---------------------- Reproducible jars ---------------------------- */
tasks.withType<AbstractArchiveTask>().configureEach { // Ensure reproducible .jars
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
}
/* ----------------------------- Shadow -------------------------------- */
tasks.shadowJar {
archiveClassifier.set("") // Use empty string instead of null.
minimize()
}
tasks.jar { archiveClassifier.set("part") } // Applies to root jarfile only.
tasks.build { dependsOn(tasks.spotlessApply) } // Build depends on spotless and shadow.
/* --------------------------- Javac opts ------------------------------- */
tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-parameters") // Enable reflection for java code.
options.isFork = true // Run javac in its own process.
options.compilerArgs.add("-Xlint:deprecation") // Trigger deprecation warning messages.
options.encoding = "UTF-8" // Use UTF-8 file encoding.
}
/* ----------------------------- Auto Formatting ------------------------ */
spotless {
java {
eclipse().configFile("config/formatter/eclipse-java-formatter.xml") // Eclipse java formatting.
leadingTabsToSpaces() // Convert leftover leading tabs to spaces.
removeUnusedImports() // Remove imports that aren't being called.
}
kotlinGradle {
ktfmt().kotlinlangStyle().configure { it.setMaxWidth(120) } // JetBrains Kotlin formatting.
target("build.gradle.kts", "settings.gradle.kts") // Gradle files to format.
}
}
checkstyle {
toolVersion = "10.18.1" // Declare checkstyle version to use.
configFile = file("config/checkstyle/checkstyle.xml") // Point checkstyle to config file.
isIgnoreFailures = true // Don't fail the build if checkstyle does not pass.
isShowViolations = true // Show the violations in any IDE with the checkstyle plugin.
}
tasks.named("compileJava") {
dependsOn("spotlessApply") // Run spotless before compiling with the JDK.
}
tasks.named("spotlessCheck") {
dependsOn("spotlessApply") // Run spotless before checking if spotless ran.
}
/* --------------------------- LuckPerms modules ------------------------ */
subprojects {
apply(plugin = "java-library")
apply(plugin = "eclipse")
group = "me.lucko.luckperms"
version = rootProject.version
repositories {
maven("https://libraries.minecraft.net") { content { includeModule("org.lwjgl", "lwjgl-freetype") } }
mavenCentral()
maven { url = uri("https://repo.lucko.me/") }
maven { url = uri("https://libraries.minecraft.net/") }
maven { url = uri("https://repo.papermc.io/repository/maven-public/") }
maven { url = uri("file://${System.getProperty("user.home")}/.m2/repository") }
System.getProperty("SELF_MAVEN_LOCAL_REPO")?.let {
val dir = file(it)
if (dir.isDirectory) {
println("Using SELF_MAVEN_LOCAL_REPO at: $it")
maven { url = uri("file://${dir.absolutePath}") }
} else {
mavenLocal()
}
}
}
tasks.withType<Test>().configureEach {
testLogging {
events("PASSED", "FAILED", "SKIPPED")
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
showExceptions = true
showCauses = true
showStackTraces = true
}
useJUnitPlatform()
}
tasks.withType<JavaCompile>().configureEach { options.encoding = "UTF-8" }
tasks.withType<Jar>().configureEach { from(rootProject.file("LICENSE.txt")) }
}
/* :api */
project(":api") {
dependencies {
compileOnly("org.checkerframework:checker-qual:3.49.3")
compileOnly("org.jetbrains:annotations:26.0.2")
}
tasks.jar { manifest { attributes(mapOf("Automatic-Module-Name" to "net.luckperms.api")) } }
}
/* :common */
project(":common") {
apply(plugin = "jacoco")
val patchedDir = layout.buildDirectory.dir("patchedSrc/commonMain/java")
val patchCommonForJ17 =
tasks.register<Copy>("patchCommonForJ17") {
from("src/main/java")
into(patchedDir)
filteringCharset = "UTF-8"
filesMatching("**/*.java") {
filter { line ->
if (
line.contains(".reversed()") &&
!line.contains("Comparator") &&
!line.contains("comparing") &&
!line.contains("thenComparing") &&
!line.contains("INSTANCE") &&
!line.contains("normal()")
) {
line.replace(
".reversed()",
".stream().collect(java.util.stream.Collectors.collectingAndThen(" +
"java.util.stream.Collectors.toList(), l -> { java.util.Collections.reverse(l); return l; }))",
)
} else line
}
}
}
sourceSets.named("main") {
java.setSrcDirs(emptyList<Any>())
java.srcDir(patchedDir)
}
tasks.named<JavaCompile>("compileJava") { dependsOn(patchCommonForJ17) }
dependencies {
testImplementation("org.slf4j:slf4j-simple:1.7.36")
testImplementation("org.junit.jupiter:junit-jupiter:5.13.0")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
testImplementation("org.testcontainers:junit-jupiter:1.21.1")
testImplementation("org.mockito:mockito-core:5.18.0")
testImplementation("org.mockito:mockito-junit-jupiter:5.18.0")
testImplementation("com.h2database:h2:2.1.214")
testImplementation("org.mongodb:mongodb-driver-legacy:5.5.0")
testImplementation("org.spongepowered:configurate-yaml:3.7.3")
testImplementation("org.spongepowered:configurate-hocon:3.7.3")
testImplementation("me.lucko.configurate:configurate-toml:3.7")
testImplementation("net.luckperms:rest-api-java-client:0.1")
api(project(":api"))
api("org.checkerframework:checker-qual:3.12.0")
compileOnly(project(":common:loader-utils"))
compileOnly("com.mojang:brigadier:1.0.18")
compileOnly("org.slf4j:slf4j-api:1.7.30")
compileOnly("org.apache.logging.log4j:log4j-api:2.14.0")
api("net.kyori:adventure-api:4.21.0") {
exclude(module = "adventure-bom")
exclude(module = "checker-qual")
exclude(module = "annotations")
}
api("net.kyori:adventure-text-serializer-gson:4.21.0") {
exclude(module = "adventure-bom")
exclude(module = "adventure-api")
exclude(module = "gson")
}
api("net.kyori:adventure-text-serializer-legacy:4.21.0") {
exclude(module = "adventure-bom")
exclude(module = "adventure-api")
}
api("net.kyori:adventure-text-serializer-plain:4.21.0") {
exclude(module = "adventure-bom")
exclude(module = "adventure-api")
}
api("net.kyori:adventure-text-minimessage:4.21.0") {
exclude(module = "adventure-bom")
exclude(module = "adventure-api")
}
api("net.kyori:event-api:3.0.0") {
exclude(module = "checker-qual")
exclude(module = "guava")
}
api("com.google.code.gson:gson:2.7")
api("com.google.guava:guava:19.0")
api("com.github.ben-manes.caffeine:caffeine:3.2.0")
api("com.squareup.okhttp3:okhttp:3.14.9")
api("com.squareup.okio:okio:1.17.6")
api("net.bytebuddy:byte-buddy:1.15.11")
api("org.spongepowered:configurate-core:3.7.3") { isTransitive = false }
api("org.spongepowered:configurate-yaml:3.7.3") { isTransitive = false }
api("org.spongepowered:configurate-gson:3.7.3") { isTransitive = false }
api("org.spongepowered:configurate-hocon:3.7.3") { isTransitive = false }
api("me.lucko.configurate:configurate-toml:3.7") { isTransitive = false }
compileOnly("com.zaxxer:HikariCP:6.3.0")
compileOnly("redis.clients:jedis:5.2.0")
compileOnly("io.nats:jnats:2.21.1")
compileOnly("com.rabbitmq:amqp-client:5.25.0")
compileOnly("org.mongodb:mongodb-driver-legacy:5.5.0")
compileOnly("org.postgresql:postgresql:42.7.6")
compileOnly("org.yaml:snakeyaml:1.33")
compileOnly("net.luckperms:rest-api-java-client:0.1")
}
}
/* :common:loader-utils */
project(":common:loader-utils") {
// nothing special
}
/* :bukkit */
project(":bukkit") {
apply(plugin = "com.gradleup.shadow")
dependencies {
implementation(project(":common"))
compileOnly(project(":common:loader-utils"))
compileOnly("com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT")
compileOnly("net.kyori:adventure-platform-bukkit:4.4.0") {
exclude(module = "adventure-bom")
exclude(module = "adventure-api")
exclude(module = "adventure-nbt")
}
compileOnly("me.lucko:commodore:2.0")
compileOnly("net.milkbowl.vault:VaultAPI:1.7") { exclude(module = "bukkit") }
compileOnly("lilypad.client.connect:api:0.0.1-SNAPSHOT")
}
tasks.named<ShadowJar>("shadowJar") {
archiveFileName.set("luckperms-bukkit.jarinjar")
dependencies { include(dependency("me.lucko.luckperms:.*")) }
relocate("net.kyori.adventure", "me.lucko.luckperms.lib.adventure")
relocate("net.kyori.event", "me.lucko.luckperms.lib.eventbus")
relocate("com.github.benmanes.caffeine", "me.lucko.luckperms.lib.caffeine")
relocate("okio", "me.lucko.luckperms.lib.okio")
relocate("okhttp3", "me.lucko.luckperms.lib.okhttp3")
relocate("net.bytebuddy", "me.lucko.luckperms.lib.bytebuddy")
relocate("me.lucko.commodore", "me.lucko.luckperms.lib.commodore")
relocate("org.mariadb.jdbc", "me.lucko.luckperms.lib.mariadb")
relocate("com.mysql", "me.lucko.luckperms.lib.mysql")
relocate("org.postgresql", "me.lucko.luckperms.lib.postgresql")
relocate("com.zaxxer.hikari", "me.lucko.luckperms.lib.hikari")
relocate("com.mongodb", "me.lucko.luckperms.lib.mongodb")
relocate("org.bson", "me.lucko.luckperms.lib.bson")
relocate("redis.clients.jedis", "me.lucko.luckperms.lib.jedis")
relocate("io.nats.client", "me.lucko.luckperms.lib.nats")
relocate("com.rabbitmq", "me.lucko.luckperms.lib.rabbitmq")
relocate("org.apache.commons.pool2", "me.lucko.luckperms.lib.commonspool2")
relocate("ninja.leaping.configurate", "me.lucko.luckperms.lib.configurate")
}
}
/* :bukkit:loader */
project(":bukkit:loader") {
apply(plugin = "com.gradleup.shadow")
dependencies {
compileOnly("com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT")
implementation(project(":api"))
implementation(project(":common:loader-utils"))
}
tasks.processResources {
filesMatching("plugin.yml") { expand(mapOf("pluginVersion" to rootProject.version.toString())) }
}
tasks.named<ShadowJar>("shadowJar") {
archiveFileName.set("LuckPerms-${rootProject.version}.jar")
from(project(":bukkit").tasks.named<ShadowJar>("shadowJar").flatMap { it.archiveFile })
manifest { attributes(mapOf("paperweight-mappings-namespace" to "mojang")) }
destinationDirectory.set(rootProject.layout.buildDirectory.dir("libs"))
}
}
/* Build root produces the server jar */
tasks.named("build") { dependsOn(project(":bukkit:loader").tasks.named("shadowJar")) }
+45
View File
@@ -0,0 +1,45 @@
plugins {
alias(libs.plugins.shadow)
}
dependencies {
implementation project(':bukkit')
implementation 'com.google.code.gson:gson:2.7'
implementation 'com.google.guava:guava:19.0'
}
shadowJar {
archiveFileName = 'luckperms-bukkitlegacy.jarinjar'
dependencies {
include(dependency('me.lucko.luckperms:.*'))
include(dependency('com.google.guava:guava:.*'))
include(dependency('com.google.code.gson:gson:.*'))
}
relocate 'com.google.common', 'me.lucko.luckperms.lib.guava'
relocate 'com.google.gson', 'me.lucko.luckperms.lib.gson'
relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
relocate 'okio', 'me.lucko.luckperms.lib.okio'
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
}
artifacts {
archives shadowJar
}
+32
View File
@@ -0,0 +1,32 @@
plugins {
alias(libs.plugins.shadow)
}
repositories {
maven { url 'https://repo.papermc.io/repository/maven-public/' }
}
dependencies {
compileOnly 'com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT'
implementation project(':api')
implementation project(':common:loader-utils')
}
processResources {
filesMatching('plugin.yml') {
expand 'pluginVersion': project.ext.fullVersion
}
}
shadowJar {
archiveFileName = "LuckPerms-Bukkit-Legacy-${project.ext.fullVersion}.jar"
from {
project(':bukkit-legacy').tasks.shadowJar.archiveFile
}
}
artifacts {
archives shadowJar
}
+57
View File
@@ -0,0 +1,57 @@
plugins {
alias(libs.plugins.shadow)
}
repositories {
maven { url 'https://repo.papermc.io/repository/maven-public/' }
}
disableAutoTargetJvm()
dependencies {
implementation project(':common')
compileOnly project(':common:loader-utils')
compileOnly 'dev.folia:folia-api:1.21.6-R0.1-SNAPSHOT'
compileOnly('net.kyori:adventure-platform-bukkit:4.4.0') {
exclude(module: 'adventure-bom')
exclude(module: 'adventure-api')
exclude(module: 'adventure-nbt')
}
compileOnly 'me.lucko:commodore:2.0'
compileOnly('net.milkbowl.vault:VaultAPI:1.7') {
exclude(module: 'bukkit')
}
compileOnly 'lilypad.client.connect:api:0.0.1-SNAPSHOT'
}
shadowJar {
archiveFileName = 'luckperms-bukkit.jarinjar'
dependencies {
include(dependency('me.lucko.luckperms:.*'))
}
relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
relocate 'okio', 'me.lucko.luckperms.lib.okio'
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
}
artifacts {
archives shadowJar
}
+36
View File
@@ -0,0 +1,36 @@
plugins {
alias(libs.plugins.shadow)
}
repositories {
maven { url 'https://repo.papermc.io/repository/maven-public/' }
}
dependencies {
compileOnly 'com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT'
implementation project(':api')
implementation project(':common:loader-utils')
}
processResources {
filesMatching('plugin.yml') {
expand 'pluginVersion': project.ext.fullVersion
}
}
shadowJar {
archiveFileName = "LuckPerms-Bukkit-${project.ext.fullVersion}.jar"
from {
project(':bukkit').tasks.shadowJar.archiveFile
}
manifest {
attributes(["paperweight-mappings-namespace": "mojang"])
}
}
artifacts {
archives shadowJar
}
@@ -10,6 +10,7 @@ load: STARTUP
# remapping when the plugin is loaded. Note that despite what this setting might otherwise imply,
# LP is still compatible with pre-1.13 releases.
api-version: 1.13
folia-supported: true
# Load LuckPerms before Vault. This means that all plugins that (soft-)depend
# on Vault depend on LuckPerms too.
@@ -25,22 +25,32 @@
package me.lucko.luckperms.bukkit;
import me.lucko.luckperms.common.plugin.scheduler.AbstractJavaScheduler;
import me.lucko.luckperms.common.plugin.scheduler.JavaSchedulerAdapter;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import me.lucko.luckperms.common.sender.Sender;
import org.bukkit.command.CommandSender;
import java.util.concurrent.Executor;
public class BukkitSchedulerAdapter extends AbstractJavaScheduler implements SchedulerAdapter {
private final Executor sync;
public class BukkitSchedulerAdapter extends JavaSchedulerAdapter implements SchedulerAdapter {
private final Executor syncExecutor;
public BukkitSchedulerAdapter(LPBukkitBootstrap bootstrap) {
super(bootstrap);
this.sync = r -> bootstrap.getServer().getScheduler().scheduleSyncDelayedTask(bootstrap.getLoader(), r);
this.syncExecutor = r -> bootstrap.getServer().getScheduler().scheduleSyncDelayedTask(bootstrap.getLoader(), r);
}
public void sync(Runnable task) {
this.syncExecutor.execute(task);
}
public void sync(CommandSender ctx, Runnable task) {
this.syncExecutor.execute(task);
}
@Override
public Executor sync() {
return this.sync;
public void sync(Sender ctx, Runnable task) {
this.syncExecutor.execute(task);
}
}
@@ -67,7 +67,7 @@ public class BukkitSenderFactory extends SenderFactory<LPBukkitPlugin, CommandSe
if (sender instanceof Player || sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) {
this.audiences.sender(sender).sendMessage(message);
} else {
getPlugin().getBootstrap().getScheduler().executeSync(() -> this.audiences.sender(sender).sendMessage(message));
getPlugin().getBootstrap().getScheduler().sync(sender, () -> this.audiences.sender(sender).sendMessage(message));
}
}
@@ -0,0 +1,86 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit;
import io.papermc.paper.threadedregions.scheduler.RegionScheduler;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import me.lucko.luckperms.common.sender.AbstractSender;
import me.lucko.luckperms.common.sender.Sender;
import org.bukkit.Server;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.ProxiedCommandSender;
import org.bukkit.command.RemoteConsoleCommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.java.JavaPlugin;
public class FoliaSchedulerAdapter extends BukkitSchedulerAdapter implements SchedulerAdapter {
private final JavaPlugin loader;
private final Server server;
public FoliaSchedulerAdapter(LPBukkitBootstrap bootstrap) {
super(bootstrap);
this.loader = bootstrap.getLoader();
this.server = bootstrap.getServer();
}
@Override
public void sync(Runnable task) {
this.server.getGlobalRegionScheduler().execute(this.loader, task);
}
@Override
public void sync(Sender ctx, Runnable task) {
sync(unwrapSender(ctx), task);
}
@Override
public void sync(CommandSender ctx, Runnable task) {
if (ctx instanceof Entity) {
((Entity) ctx).getScheduler().execute(this.loader, task, null, 0);
} else if (ctx instanceof BlockCommandSender) {
RegionScheduler scheduler = this.server.getRegionScheduler();
scheduler.execute(this.loader, ((BlockCommandSender) ctx).getBlock().getLocation(), task);
} else if (ctx instanceof ConsoleCommandSender || ctx instanceof RemoteConsoleCommandSender) {
this.server.getGlobalRegionScheduler().execute(this.loader, task);
} else if (ctx instanceof ProxiedCommandSender) {
sync(((ProxiedCommandSender) ctx).getCallee(), task);
} else {
throw new IllegalArgumentException("Unknown command sender type: " + ctx.getClass().getName());
}
}
@SuppressWarnings("unchecked")
private static CommandSender unwrapSender(Sender sender) {
if (sender instanceof AbstractSender) {
return ((AbstractSender<CommandSender>) sender).getSender();
} else {
throw new IllegalArgumentException("unknown sender type: " + sender.getClass());
}
}
}
@@ -102,7 +102,9 @@ public class LPBukkitBootstrap implements LuckPermsBootstrap, LoaderBootstrap, B
this.loader = loader;
this.logger = new JavaPluginLogger(loader.getLogger());
this.schedulerAdapter = new BukkitSchedulerAdapter(this);
this.schedulerAdapter = isFolia()
? new FoliaSchedulerAdapter(this)
: new BukkitSchedulerAdapter(this);
this.classPathAppender = new JarInJarClassPathAppender(getClass().getClassLoader());
this.console = new NullSafeConsoleCommandSender(getServer());
this.plugin = new LPBukkitPlugin(this);
@@ -175,7 +177,7 @@ public class LPBukkitBootstrap implements LuckPermsBootstrap, LoaderBootstrap, B
this.plugin.enable();
// schedule a task to update the 'serverStarting' flag
getServer().getScheduler().runTask(this.loader, () -> this.serverStarting = false);
this.schedulerAdapter.sync(() -> this.serverStarting = false);
} finally {
this.enableLatch.countDown();
}
@@ -307,8 +309,17 @@ public class LPBukkitBootstrap implements LuckPermsBootstrap, LoaderBootstrap, B
try {
Class.forName("com.google.gson.JsonElement");
return false;
} catch (Exception e) {
} catch (ClassNotFoundException e) {
return true;
}
}
private static boolean isFolia() {
try {
Class.forName("io.papermc.paper.threadedregions.scheduler.RegionScheduler");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
@@ -206,7 +206,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
// schedule another injection after all plugins have loaded
// the entire pluginmanager instance is replaced by some plugins :(
this.bootstrap.getServer().getScheduler().runTaskLaterAsynchronously(this.bootstrap.getLoader(), injector, 1);
this.bootstrap.getScheduler().sync(injector);
}
/*
@@ -221,12 +221,10 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
* - https://hub.spigotmc.org/jira/browse/SPIGOT-5546
* - https://github.com/PaperMC/Paper/pull/3509
*/
if (getConfiguration().get(ConfigKeys.VAULT_ENABLED)) {
PluginManagerUtil.injectDependency(this.bootstrap.getServer().getPluginManager(), this.bootstrap.getLoader().getName(), "Vault");
PluginManagerUtil.injectDependency(this.bootstrap.getServer().getPluginManager(), this.bootstrap.getLoader().getName(), "Vault");
// Provide vault support
tryVaultHook(false);
}
// Provide vault support
tryVaultHook(false);
}
@Override
@@ -239,10 +237,6 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
return; // already hooked
}
if (!getConfiguration().get(ConfigKeys.VAULT_ENABLED)) {
return; // disabled in config
}
try {
if (force || this.bootstrap.getServer().getPluginManager().isPluginEnabled("Vault")) {
this.vaultHookManager = new VaultHookManager(this);
@@ -274,7 +268,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
// remove all operators on startup if they're disabled
if (!getConfiguration().get(ConfigKeys.OPS_ENABLED)) {
this.bootstrap.getServer().getScheduler().runTaskAsynchronously(this.bootstrap.getLoader(), () -> {
this.bootstrap.getScheduler().sync(() -> {
for (OfflinePlayer player : this.bootstrap.getServer().getOperators()) {
player.setOp(false);
}
@@ -293,11 +287,11 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
// Load any online users (in the case of a reload)
for (Player player : this.bootstrap.getServer().getOnlinePlayers()) {
this.bootstrap.getScheduler().executeAsync(() -> {
this.bootstrap.getScheduler().async(() -> {
try {
User user = this.connectionListener.loadUser(player.getUniqueId(), player.getName());
if (user != null) {
this.bootstrap.getScheduler().executeSync(() -> {
this.bootstrap.getScheduler().sync(player, () -> {
try {
LuckPermsPermissible lpPermissible = new LuckPermsPermissible(player, user, this);
PermissibleInjector.inject(player, lpPermissible, getLogger());
@@ -353,7 +347,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
try {
Class.forName(className);
return true;
} catch (Exception e) {
} catch (ClassNotFoundException e) {
return false;
}
}
@@ -83,7 +83,7 @@ public class BukkitAutoOpListener implements LuckPermsEventListener {
if (callerIsSync) {
player.setOp(value);
} else {
this.plugin.getBootstrap().getScheduler().executeSync(() -> player.setOp(value));
this.plugin.getBootstrap().getScheduler().sync(player, () -> player.setOp(value));
}
}
@@ -26,6 +26,7 @@
package me.lucko.luckperms.bukkit.listeners;
import com.github.benmanes.caffeine.cache.LoadingCache;
import me.lucko.luckperms.bukkit.LPBukkitBootstrap;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.cache.BufferedRequest;
import me.lucko.luckperms.common.event.LuckPermsEventListener;
@@ -90,12 +91,15 @@ public class BukkitCommandListUpdater implements LuckPermsEventListener {
// Called when the buffer times out.
private void sendUpdate(UUID uniqueId) {
if (this.plugin.getBootstrap().isServerStopping()) {
LPBukkitBootstrap bootstrap = this.plugin.getBootstrap();
if (bootstrap.isServerStopping()) {
return;
}
this.plugin.getBootstrap().getScheduler().sync()
.execute(() -> this.plugin.getBootstrap().getPlayer(uniqueId).ifPresent(Player::updateCommands));
Player player = bootstrap.getPlayer(uniqueId).orElse(null);
if (player != null) {
bootstrap.getScheduler().sync(player, player::updateCommands);
}
}
private final class SendBuffer extends BufferedRequest<Void> {
@@ -240,7 +240,7 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
// perform unhooking from bukkit objects 1 tick later.
// this allows plugins listening after us on MONITOR to still have intact permissions data
this.plugin.getBootstrap().getServer().getScheduler().runTaskLater(this.plugin.getLoader(), () -> {
this.plugin.getBootstrap().getScheduler().sync(() -> {
// Remove the custom permissible
try {
PermissibleInjector.uninject(player, true);
@@ -253,7 +253,7 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
if (this.plugin.getConfiguration().get(ConfigKeys.AUTO_OP)) {
player.setOp(false);
}
}, 1L);
});
}
}
@@ -94,10 +94,6 @@ public class BukkitPlatformListener implements Listener {
@EventHandler
public void onPluginEnable(PluginEnableEvent e) {
if (!this.plugin.getConfiguration().get(ConfigKeys.VAULT_ENABLED)) {
return;
}
Plugin p = e.getPlugin();
boolean shouldHook = p.getName().equalsIgnoreCase("Vault") ||
(PLUGIN_DESCRIPTION_FILE_PROVIDES_SUPPORTED && p.getDescription().getProvides().contains("Vault"));
@@ -77,7 +77,7 @@ public class LilyPadMessenger implements Messenger {
@EventListener
public void onMessage(MessageEvent event) {
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
this.plugin.getBootstrap().getScheduler().async(() -> {
String channel = event.getChannel();
if (!channel.equals(CHANNEL)) {
return;
@@ -25,6 +25,7 @@
package me.lucko.luckperms.bukkit.util;
import net.kyori.adventure.text.Component;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.command.ConsoleCommandSender;
@@ -35,9 +36,12 @@ import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
/**
* The {@link Server#getConsoleSender()} method returns null during onEnable
@@ -109,12 +113,16 @@ public class NullSafeConsoleCommandSender implements ConsoleCommandSender {
// just throw UnsupportedOperationException - we never use any of these methods
@Override public @NonNull Spigot spigot() { throw new UnsupportedOperationException(); }
@Override public void sendMessage(@Nullable UUID uuid, @NotNull String s) { throw new UnsupportedOperationException(); }
@Override public void sendMessage(@Nullable UUID uuid, @NotNull String... strings) { throw new UnsupportedOperationException(); }
@Override public @NotNull Component name() { throw new UnsupportedOperationException(); }
@Override public boolean isConversing() { throw new UnsupportedOperationException(); }
@Override public void acceptConversationInput(@NonNull String s) { throw new UnsupportedOperationException(); }
@Override public boolean beginConversation(@NonNull Conversation conversation) { throw new UnsupportedOperationException(); }
@Override public void abandonConversation(@NonNull Conversation conversation) { throw new UnsupportedOperationException(); }
@Override public void abandonConversation(@NonNull Conversation conversation, @NonNull ConversationAbandonedEvent conversationAbandonedEvent) { throw new UnsupportedOperationException(); }
@Override public void sendRawMessage(@NonNull String s) { throw new UnsupportedOperationException(); }
@Override public void sendRawMessage(@Nullable UUID uuid, @NotNull String s) { throw new UnsupportedOperationException(); }
@Override public @NonNull PermissionAttachment addAttachment(@NonNull Plugin plugin, @NonNull String s, boolean b) { throw new UnsupportedOperationException(); }
@Override public @NonNull PermissionAttachment addAttachment(@NonNull Plugin plugin) { throw new UnsupportedOperationException(); }
@Override public PermissionAttachment addAttachment(@NonNull Plugin plugin, @NonNull String s, boolean b, int i) { throw new UnsupportedOperationException(); }
+20 -31
View File
@@ -41,7 +41,7 @@ server: global
# - To get around this, you can use a player's uuid directly in the command, or enable this option.
# - When this is set to 'true', the server facility is used. This may use a number of methods,
# including checking the servers local cache, or making a request to the Mojang API.
use-server-uuid-cache: true
use-server-uuid-cache: false
@@ -83,7 +83,7 @@ use-server-uuid-cache: true
#
# - A H2 database is the default option.
# - If you want to edit data manually in "traditional" storage files, we suggest using YAML.
storage-method: postgresql
storage-method: h2
# The following block defines the settings for remote database storage methods.
#
@@ -99,11 +99,11 @@ data:
# The name of the database to store LuckPerms data in.
# - This must be created already. Don't worry about this setting if you're using MongoDB.
database: luckperms
database: minecraft
# Credentials for the database.
username: '^{POSTGRES_USER}'
password: '^{POSTGRES_PASSWORD}'
username: root
password: ''
# These settings apply to the MySQL connection pool.
# - The default values will be suitable for the majority of users.
@@ -132,11 +132,11 @@ data:
# from being timed out by the database or network infrastructure, measured in milliseconds.
# - The value should be less than maximum-lifetime and greater than 30000 (30 seconds).
# - Setting the value to zero will disable the keepalive functionality.
keepalive-time: 120000
keepalive-time: 0
# This setting controls the maximum number of milliseconds that the plugin will wait for a
# connection from the pool, before timing out.
connection-timeout: 10000 # 10 seconds
connection-timeout: 5000 # 5 seconds
# This setting allows you to define extra properties for connections.
#
@@ -216,7 +216,7 @@ sync-minutes: -1
# - When using a file-based storage type, LuckPerms can monitor the data files for changes, and
# automatically update when changes are detected.
# - If you don't want this feature to be active, set this option to false.
watch-files: false
watch-files: true
# Define which messaging service should be used by the plugin.
#
@@ -258,16 +258,16 @@ push-log-entries: true
# - If you have LuckPerms installed on your backend servers as well as a BungeeCord proxy, you
# should set this option to false on either your backends or your proxies, to avoid players being
# messaged twice about log entries.
broadcast-received-log-entries: false
broadcast-received-log-entries: true
# Settings for Keydb.
# Settings for Redis.
# Port 6379 is used by default; set address to "host:port" if differs
# Multiple Keydb nodes can be specified in the same format as a string list under the name "addresses".
# Multiple Redis nodes can be specified in the same format as a string list under the name "addresses".
redis:
enabled: true
enabled: false
address: localhost
username: 'default'
password: 'bookchin'
username: ''
password: ''
# Settings for Nats.
# Port 4222 is used by default; set address to "host:port" if differs
@@ -335,7 +335,7 @@ argument-based-command-permissions: false
# If the plugin should check whether senders are a member of a given group before they're able to
# edit the groups data or add/remove other users to/from it.
# Note: these limitations do not apply to the web editor!
require-sender-group-membership-to-modify: true
require-sender-group-membership-to-modify: false
# If the plugin should send log notifications to users whenever permissions are modified.
#
@@ -408,14 +408,14 @@ meta-formatting:
duplicates: first-only
start-spacer: ""
middle-spacer: " "
end-spacer: " "
end-spacer: ""
suffix:
format:
- "highest"
duplicates: first-only
start-spacer: " "
start-spacer: ""
middle-spacer: " "
end-spacer: " "
end-spacer: ""
@@ -627,19 +627,8 @@ commands-allow-op: true
# +----------------------------------------------------------------------------------------------+ #
# | Vault integration settings | #
# | | #
# | Disabled by default (vault-enabled: false). The remaining vault-* settings below only take | #
# | effect when vault-enabled is set to true. | #
# +----------------------------------------------------------------------------------------------+ #
# If the Vault API bridge should be registered.
#
# - When false (default), LuckPerms will not hook into Vault at all. Vault-dependent plugins will
# fall back to SuperPerms and will not see LuckPerms groups, prefixes, or meta.
# - When true, LuckPerms will register Vault permission and chat providers if the Vault plugin is
# installed. Required for any plugin that reads groups/prefix/suffix via the Vault API.
vault-enabled: false
# If Vault lookups for offline players on the main server thread should be enabled.
#
# LuckPerms has a "catch" for plugins attempting to perform unsafe offline player data lookups
@@ -741,7 +730,7 @@ resolve-command-selectors: false
#
# Note: This does not affect interactions with LuckPerms via the API.
commands-read-only-mode:
players: true
players: false
console: false
# If LuckPerms commands should be disabled. When true, this will prevent all LP commands from being
@@ -758,5 +747,5 @@ commands-read-only-mode:
#
# Note: This does not affect interactions with LuckPerms via the API.
disable-luckperms-commands:
players: true
players: false
console: false
+49
View File
@@ -0,0 +1,49 @@
plugins {
alias(libs.plugins.shadow)
}
dependencies {
implementation project(':common')
compileOnly project(':common:loader-utils')
compileOnly('net.md-5:bungeecord-api:1.19-R0.1-SNAPSHOT') {
exclude(module: 'bungeecord-protocol')
}
compileOnly('net.kyori:adventure-platform-bungeecord:4.4.0') {
exclude(module: 'adventure-bom')
exclude(module: 'adventure-api')
exclude(module: 'adventure-nbt')
}
compileOnly 'com.imaginarycode.minecraft:RedisBungee:0.4'
}
shadowJar {
archiveFileName = 'luckperms-bungee.jarinjar'
dependencies {
include(dependency('me.lucko.luckperms:.*'))
}
relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
relocate 'okio', 'me.lucko.luckperms.lib.okio'
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
}
artifacts {
archives shadowJar
}
+30
View File
@@ -0,0 +1,30 @@
plugins {
alias(libs.plugins.shadow)
}
dependencies {
compileOnly('net.md-5:bungeecord-api:1.19-R0.1-SNAPSHOT') {
exclude(module: 'bungeecord-protocol')
}
implementation project(':api')
implementation project(':common:loader-utils')
}
processResources {
filesMatching('plugin.yml') {
expand 'pluginVersion': project.ext.fullVersion
}
}
shadowJar {
archiveFileName = "LuckPerms-Bungee-${project.ext.fullVersion}.jar"
from {
project(':bungee').tasks.shadowJar.archiveFile
}
}
artifacts {
archives shadowJar
}
@@ -52,11 +52,6 @@ public class BungeeSchedulerAdapter implements SchedulerAdapter {
return this.executor;
}
@Override
public Executor sync() {
return this.executor;
}
@Override
public SchedulerTask asyncLater(Runnable task, long delay, TimeUnit unit) {
ScheduledTask t = this.bootstrap.getProxy().getScheduler().schedule(this.bootstrap.getLoader(), task, delay, unit);
@@ -302,7 +302,7 @@ public class LPBungeeBootstrap implements LuckPermsBootstrap, LoaderBootstrap, B
try {
Class.forName("com.google.gson.internal.bind.TreeTypeAdapter");
return false;
} catch (Exception e) {
} catch (ClassNotFoundException e) {
return true;
}
}
@@ -77,7 +77,7 @@ public class BungeeConnectionListener extends AbstractConnectionListener impleme
this will prevent the event from completing until we're finished handling. */
e.registerIntent(this.plugin.getLoader());
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
this.plugin.getBootstrap().getScheduler().async(() -> {
/* Actually process the login for the connection.
We do this here to delay the login until the data is ready.
If the login gets cancelled later on, then this will be cleaned up.
@@ -83,7 +83,7 @@ public class PluginMessageMessenger extends AbstractPluginMessageMessenger imple
if (handleIncomingMessage(buf)) {
// Forward to other servers
this.plugin.getBootstrap().getScheduler().executeAsync(() -> sendOutgoingMessage(buf));
this.plugin.getBootstrap().getScheduler().async(() -> sendOutgoingMessage(buf));
}
}
}
+107
View File
@@ -0,0 +1,107 @@
plugins {
id("java-library")
id("jacoco")
}
test {
useJUnitPlatform {
if (!project.hasProperty('dockerTests')) {
excludeTags 'docker'
}
}
}
jacocoTestReport {
dependsOn test
}
dependencies {
testImplementation 'org.slf4j:slf4j-simple:1.7.36'
testImplementation 'org.junit.jupiter:junit-jupiter:5.13.0'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation 'org.testcontainers:junit-jupiter:1.21.1'
testImplementation 'org.mockito:mockito-core:5.18.0'
testImplementation 'org.mockito:mockito-junit-jupiter:5.18.0'
testImplementation 'com.h2database:h2:2.1.214'
testImplementation 'org.mongodb:mongodb-driver-legacy:5.5.0'
testImplementation 'org.spongepowered:configurate-yaml:3.7.3'
testImplementation 'org.spongepowered:configurate-hocon:3.7.3'
testImplementation 'me.lucko.configurate:configurate-toml:3.7'
testImplementation 'net.luckperms:rest-api-java-client:0.1'
api project(':api')
api 'org.checkerframework:checker-qual:3.12.0'
compileOnly project(':common:loader-utils')
compileOnly 'com.mojang:brigadier:1.0.18'
compileOnly 'org.slf4j:slf4j-api:1.7.30'
compileOnly 'org.apache.logging.log4j:log4j-api:2.14.0'
api('net.kyori:adventure-api:4.21.0') {
exclude(module: 'adventure-bom')
exclude(module: 'checker-qual')
exclude(module: 'annotations')
}
api('net.kyori:adventure-text-serializer-gson:4.21.0') {
exclude(module: 'adventure-bom')
exclude(module: 'adventure-api')
exclude(module: 'gson')
}
api('net.kyori:adventure-text-serializer-legacy:4.21.0') {
exclude(module: 'adventure-bom')
exclude(module: 'adventure-api')
}
api('net.kyori:adventure-text-serializer-plain:4.21.0') {
exclude(module: 'adventure-bom')
exclude(module: 'adventure-api')
}
api("net.kyori:adventure-text-minimessage:4.21.0") {
exclude(module: 'adventure-bom')
exclude(module: 'adventure-api')
}
api('net.kyori:event-api:3.0.0') {
exclude(module: 'checker-qual')
exclude(module: 'guava')
}
api 'com.google.code.gson:gson:2.7'
api 'com.google.guava:guava:19.0'
api 'com.github.ben-manes.caffeine:caffeine:3.2.0'
api 'com.squareup.okhttp3:okhttp:3.14.9'
api 'com.squareup.okio:okio:1.17.6'
api 'net.bytebuddy:byte-buddy:1.15.11'
api('org.spongepowered:configurate-core:3.7.3') {
transitive = false
}
api('org.spongepowered:configurate-yaml:3.7.3') {
transitive = false
}
api('org.spongepowered:configurate-gson:3.7.3') {
transitive = false
}
api('org.spongepowered:configurate-hocon:3.7.3') {
transitive = false
}
api('me.lucko.configurate:configurate-toml:3.7') {
transitive = false
}
compileOnly 'com.zaxxer:HikariCP:6.3.0'
compileOnly 'redis.clients:jedis:5.2.0'
compileOnly 'io.nats:jnats:2.21.1'
compileOnly 'com.rabbitmq:amqp-client:5.25.0'
compileOnly 'org.mongodb:mongodb-driver-legacy:5.5.0'
compileOnly 'org.postgresql:postgresql:42.7.6'
compileOnly 'org.yaml:snakeyaml:1.33'
compileOnly 'net.luckperms:rest-api-java-client:0.1'
}
+1
View File
@@ -0,0 +1 @@
// nothing special to do here (yet)!
@@ -155,7 +155,7 @@ public class CommandManager {
public CompletableFuture<Void> executeCommand(Sender sender, String label, List<String> args) {
UUID uniqueId = sender.getUniqueId();
if (this.plugin.getConfiguration().get(ConfigKeys.COMMANDS_RATE_LIMIT) && !sender.isConsole() && !Sender.CONSOLE_UUID.equals(uniqueId) && !this.playerRateLimit.add(uniqueId)) {
if (this.plugin.getConfiguration().get(ConfigKeys.COMMANDS_RATE_LIMIT) && !sender.isConsole() && !this.playerRateLimit.add(uniqueId)) {
this.plugin.getLogger().warn("Player '" + uniqueId + "' is spamming LuckPerms commands. Ignoring further inputs.");
return CompletableFuture.completedFuture(null);
}
@@ -113,7 +113,7 @@ public class ExportCommand extends SingleCommand {
}
// Run the exporter in its own thread.
plugin.getBootstrap().getScheduler().executeAsync(() -> {
plugin.getBootstrap().getScheduler().async(() -> {
try {
exporter.run();
} finally {
@@ -133,7 +133,7 @@ public class ImportCommand extends SingleCommand {
Importer importer = new Importer(plugin, sender, data, !args.contains("--replace"));
// Run the importer in its own thread.
plugin.getBootstrap().getScheduler().executeAsync(() -> {
plugin.getBootstrap().getScheduler().async(() -> {
try {
importer.run();
} finally {
@@ -94,7 +94,7 @@ public class VerboseCommand extends SingleCommand {
String commandWithSlash = String.join(" ", args.subList(2, args.size()));
String command = commandWithSlash.charAt(0) == '/' ? commandWithSlash.substring(1) : commandWithSlash;
plugin.getBootstrap().getScheduler().sync().execute(() -> {
plugin.getBootstrap().getScheduler().sync(executor, () -> {
Message.VERBOSE_ON_COMMAND.send(sender, executor.getName(), command);
verboseHandler.registerListener(sender, VerboseFilter.acceptAll(), true);
@@ -493,12 +493,6 @@ public final class ConfigKeys {
*/
public static final ConfigKey<Boolean> COMMANDS_RATE_LIMIT = booleanKey("commands-rate-limit", true);
/**
* If the Vault API bridge should be registered on platforms that support it (Bukkit).
* Disabled by default; the remaining vault-* keys below only take effect when this is true.
*/
public static final ConfigKey<Boolean> VAULT_ENABLED = booleanKey("vault-enabled", false);
/**
* If Vault lookups for offline players on the main server thread should be enabled
*/
@@ -143,7 +143,7 @@ public class DependencyRegistry {
try {
Class.forName(className);
return true;
} catch (Exception e) {
} catch (ClassNotFoundException e) {
return false;
}
}
@@ -140,7 +140,7 @@ public final class EventDispatcher {
}
// async: generate an event class and post it
this.eventBus.getPlugin().getBootstrap().getScheduler().executeAsync(() -> post(eventClass, params));
this.eventBus.getPlugin().getBootstrap().getScheduler().async(() -> post(eventClass, params));
}
private void postSync(Class<? extends LuckPermsEvent> eventClass, Object... params) {
@@ -231,11 +231,11 @@ public final class EventDispatcher {
}
public void dispatchNodeChanges(PermissionHolder target, DataType dataType, Difference<Node> changes) {
if (changes.isEmpty()) {
if (!this.eventBus.shouldPost(NodeAddEvent.class) && !this.eventBus.shouldPost(NodeRemoveEvent.class)) {
return;
}
if (!this.eventBus.shouldPost(NodeAddEvent.class) && !this.eventBus.shouldPost(NodeRemoveEvent.class)) {
if (changes.isEmpty()) {
return;
}
@@ -88,7 +88,7 @@ public class TranslationRepository {
return; // skip
}
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
this.plugin.getBootstrap().getScheduler().async(() -> {
// cleanup old translation files
clearDirectory(this.plugin.getTranslationManager().getTranslationsDirectory(), Files::isRegularFile);
@@ -113,7 +113,7 @@ public class PostgresMessenger implements Messenger {
try {
this.listener = new NotificationListener();
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
this.plugin.getBootstrap().getScheduler().async(() -> {
this.listener.listenAndBind();
if (!firstStartup) {
this.plugin.getLogger().info("Postgres listen/notify connection re-established");
@@ -73,7 +73,7 @@ public class RedisMessenger implements Messenger {
private void init(UnifiedJedis jedis) {
this.jedis = jedis;
this.sub = new Subscription(this);
this.plugin.getBootstrap().getScheduler().executeAsync(this.sub);
this.plugin.getBootstrap().getScheduler().async(this.sub);
}
private static JedisClientConfig jedisConfig(String username, String password, boolean ssl) {
@@ -431,8 +431,8 @@ public abstract class PermissionHolder {
Difference<Node> result = getData(dataType).removeIf(Node::hasExpired);
if (!result.isEmpty()) {
invalidateCache();
this.plugin.getEventDispatcher().dispatchNodeChanges(this, dataType, result);
}
this.plugin.getEventDispatcher().dispatchNodeChanges(this, dataType, result);
return !result.isEmpty();
}
@@ -235,7 +235,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
this.apiProvider = new LuckPermsApiProvider(this);
this.apiProvider.ensureApiWasLoadedByPlugin();
this.eventDispatcher = new EventDispatcher(provideEventBus(this.apiProvider));
getBootstrap().getScheduler().executeAsync(GeneratedEventClass::preGenerate);
getBootstrap().getScheduler().async(GeneratedEventClass::preGenerate);
ApiRegistrationUtil.registerProvider(this.apiProvider);
registerApiOnPlatform(this.apiProvider);
@@ -44,7 +44,7 @@ import java.util.stream.Collectors;
/**
* Abstract implementation of {@link SchedulerAdapter} using a {@link ScheduledExecutorService}.
*/
public abstract class AbstractJavaScheduler implements SchedulerAdapter {
public class JavaSchedulerAdapter implements SchedulerAdapter {
private static final int PARALLELISM = 16;
private final LuckPermsBootstrap bootstrap;
@@ -52,7 +52,7 @@ public abstract class AbstractJavaScheduler implements SchedulerAdapter {
private final ScheduledThreadPoolExecutor scheduler;
private final ForkJoinPool worker;
public AbstractJavaScheduler(LuckPermsBootstrap bootstrap) {
public JavaSchedulerAdapter(LuckPermsBootstrap bootstrap) {
this.bootstrap = bootstrap;
this.scheduler = new ScheduledThreadPoolExecutor(1, r -> {
@@ -133,7 +133,7 @@ public abstract class AbstractJavaScheduler implements SchedulerAdapter {
private final class ExceptionHandler implements UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
AbstractJavaScheduler.this.bootstrap.getPluginLogger().warn("Thread " + t.getName() + " threw an uncaught exception", e);
JavaSchedulerAdapter.this.bootstrap.getPluginLogger().warn("Thread " + t.getName() + " threw an uncaught exception", e);
}
}
}
@@ -25,6 +25,8 @@
package me.lucko.luckperms.common.plugin.scheduler;
import me.lucko.luckperms.common.sender.Sender;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -33,6 +35,15 @@ import java.util.concurrent.TimeUnit;
*/
public interface SchedulerAdapter {
/**
* Executes a task sync
*
* @param task the task
*/
default void sync(Sender ctx, Runnable task) {
async(task);
}
/**
* Gets an async executor instance
*
@@ -40,31 +51,15 @@ public interface SchedulerAdapter {
*/
Executor async();
/**
* Gets a sync executor instance
*
* @return a sync executor instance
*/
Executor sync();
/**
* Executes a task async
*
* @param task the task
*/
default void executeAsync(Runnable task) {
default void async(Runnable task) {
async().execute(task);
}
/**
* Executes a task sync
*
* @param task the task
*/
default void executeSync(Runnable task) {
sync().execute(task);
}
/**
* Executes the given task with a delay.
*
@@ -95,7 +90,7 @@ public interface SchedulerAdapter {
/**
* Shuts down the executor instance.
*
* <p>{@link #async()} and {@link #executeAsync(Runnable)}.</p>
* <p>{@link #async()} and {@link #async(Runnable)}.</p>
*/
void shutdownExecutor();
@@ -117,7 +117,7 @@ public abstract class AbstractConnectionListener {
this.plugin.getUserManager().getHouseKeeper().registerUsage(uniqueId);
// force a clear of transient nodes
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
this.plugin.getBootstrap().getScheduler().async(() -> {
User user = this.plugin.getUserManager().getIfLoaded(uniqueId);
if (user != null) {
user.clearNodes(DataType.TRANSIENT, null, false);
@@ -69,6 +69,10 @@ public final class AbstractSender<T> implements Sender {
return this.plugin;
}
public T getSender() {
return this.sender;
}
@Override
public UUID getUniqueId() {
return this.uniqueId;
@@ -58,7 +58,7 @@ public class FileWatcher extends AbstractFileWatcher {
this.basePath = basePath;
super.registerRecursively(basePath);
plugin.getBootstrap().getScheduler().executeAsync(super::runEventProcessingLoop);
plugin.getBootstrap().getScheduler().async(super::runEventProcessingLoop);
}
/**
@@ -66,7 +66,7 @@ public class HandlerChangeRequest implements Handler {
}
// send "change-accepted" response
this.socket.getPlugin().getBootstrap().getScheduler().executeAsync(() ->
this.socket.getPlugin().getBootstrap().getScheduler().async(() ->
this.socket.send(SocketMessageType.CHANGE_RESPONSE.builder()
.add("state", STATE_ACCEPTED)
.toJson()
@@ -80,7 +80,7 @@ public class WebEditorSocketListener extends WebSocketListener {
@Override
public void onMessage(@NonNull WebSocket webSocket, @NonNull String msg) {
this.socket.getPlugin().getBootstrap().getScheduler().executeAsync(() -> {
this.socket.getPlugin().getBootstrap().getScheduler().async(() -> {
this.lock.lock();
try {
if (shouldIgnoreMessages()) {
@@ -0,0 +1,298 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.locale;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import me.lucko.luckperms.common.actionlog.LoggedAction;
import me.lucko.luckperms.common.command.spec.Argument;
import me.lucko.luckperms.common.command.spec.CommandSpec;
import me.lucko.luckperms.common.context.ImmutableContextSetImpl;
import me.lucko.luckperms.common.extension.SimpleExtensionManager;
import me.lucko.luckperms.common.model.HolderType;
import me.lucko.luckperms.common.model.InheritanceOrigin;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.PermissionHolderIdentifier;
import me.lucko.luckperms.common.node.types.Inheritance;
import me.lucko.luckperms.common.node.types.Meta;
import me.lucko.luckperms.common.node.types.Permission;
import me.lucko.luckperms.common.node.types.Prefix;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
import me.lucko.luckperms.common.storage.Storage;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentIteratorFlag;
import net.kyori.adventure.text.ComponentIteratorType;
import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.translation.TranslationRegistry;
import net.kyori.adventure.util.UTF8ResourceBundleControl;
import net.luckperms.api.actionlog.Action;
import net.luckperms.api.context.ContextSet;
import net.luckperms.api.model.data.DataType;
import net.luckperms.api.node.Node;
import net.luckperms.api.node.metadata.types.InheritanceOriginMetadata;
import net.luckperms.api.node.types.ChatMetaNode;
import net.luckperms.api.node.types.InheritanceNode;
import net.luckperms.api.node.types.MetaNode;
import net.luckperms.api.platform.Platform;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Answers;
import org.mockito.junit.jupiter.MockitoExtension;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.MessageFormat;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
@ExtendWith(MockitoExtension.class)
public class MessageTest {
private static final Set<Class<?>> MESSAGE_CLASSES = ImmutableSet.of(
Message.Args0.class,
Message.Args1.class,
Message.Args2.class,
Message.Args3.class,
Message.Args4.class,
Message.Args5.class,
Message.Args6.class
);
private static final Set<String> IGNORED_MISSING_TRANSLATION_KEYS = ImmutableSet.of(
"luckperms.command.misc.invalid-input-empty-stub"
);
private static TranslationRegistry registry;
private static Set<String> translationKeys;
@BeforeAll
public static void setupRenderer() {
registry = TranslationRegistry.create(Key.key("luckperms", "test"));
ResourceBundle bundle = ResourceBundle.getBundle("luckperms", Locale.ENGLISH, UTF8ResourceBundleControl.get());
translationKeys = ImmutableSet.copyOf(bundle.keySet());
registry.registerAll(Locale.ENGLISH, bundle, false);
}
private static Stream<Field> getMessageFields() {
return Arrays.stream(Message.class.getDeclaredFields())
.filter(f -> Modifier.isStatic(f.getModifiers()))
.filter(f -> MESSAGE_CLASSES.contains(f.getType()));
}
@ParameterizedTest
@MethodSource("getMessageFields")
public void testMessage(Field field) {
Component baseComponent = buildMessage(field);
for (Component part : getNestedComponents(baseComponent)) {
if (part instanceof TranslatableComponent) {
TranslatableComponent component = (TranslatableComponent) part;
assertTranslatableComponentValid(component);
}
}
}
@ParameterizedTest
@EnumSource
public void testCommandUsageMessages(CommandSpec commandSpec) {
assertTranslatableComponentValid(commandSpec.description());
List<Argument> args = commandSpec.args();
if (args != null) {
for (Argument arg : args) {
assertTranslatableComponentValid(arg.getDescription());
}
}
}
private static void assertTranslatableComponentValid(TranslatableComponent component) {
String key = component.key();
if (IGNORED_MISSING_TRANSLATION_KEYS.contains(key)) {
return;
}
assertTrue(translationKeys.contains(key), "unknown translation key: " + key);
List<Component> args = component.args();
MessageFormat fmt = registry.translate(key, Locale.ENGLISH);
assertNotNull(fmt);
assertEquals(fmt.getFormats().length, args.size(), "number of formats in translation for " + key + " does not match number of arguments");
}
private static Iterable<Component> getNestedComponents(Component component) {
return component.iterable(
ComponentIteratorType.BREADTH_FIRST,
ImmutableSet.of(ComponentIteratorFlag.INCLUDE_TRANSLATABLE_COMPONENT_ARGUMENTS, ComponentIteratorFlag.INCLUDE_HOVER_SHOW_TEXT_COMPONENT)
);
}
private static Component buildMessage(Field field) {
Class<?> type = field.getType();
List<Method> buildMethods = Arrays.stream(type.getDeclaredMethods())
.filter(method -> method.getName().equals("build"))
.collect(Collectors.toList());
if (buildMethods.size() != 1) {
throw new IllegalStateException("Expected exactly one build() method - " + buildMethods);
}
Method buildMethod = buildMethods.get(0);
Object[] parameters = new Object[buildMethod.getParameterCount()];
if (buildMethod.getParameterCount() != 0) {
Type genericType = field.getGenericType();
Type[] typeArguments = ((ParameterizedType) genericType).getActualTypeArguments();
for (int i = 0; i < typeArguments.length; i++) {
Type typeArgument = typeArguments[i];
parameters[i] = mockArgument(typeArgument);
}
}
try {
Object builder = field.get(null);
return (Component) buildMethod.invoke(builder, parameters);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
private static Object mockArgument(Type type) {
if (type instanceof ParameterizedType) {
return mockArgument(((ParameterizedType) type).getRawType());
}
Class<?> clazz = (Class<?>) type;
if (clazz == String.class) {
return "stub";
} else if (clazz == Integer.class) {
return 0;
} else if (clazz == Boolean.class) {
return false;
} else if (clazz == Double.class) {
return 0d;
} else if (clazz == LoggedAction.class) {
return LoggedAction.build()
.source(UUID.randomUUID())
.sourceName("stub")
.targetType(Action.Target.Type.GROUP)
.targetName("stub")
.description("stub")
.build();
} else if (clazz == Node.class) {
return Permission.builder().permission("stub").expiry(1, TimeUnit.MINUTES).build();
} else if (clazz == InheritanceNode.class) {
return Inheritance.builder().group("stub").expiry(1, TimeUnit.MINUTES).build();
} else if (clazz == MetaNode.class) {
return Meta.builder("stub", "stub")
.withMetadata(InheritanceOriginMetadata.KEY, new InheritanceOrigin(
new PermissionHolderIdentifier(HolderType.GROUP, "stub"),
DataType.NORMAL
))
.build();
} else if (clazz == ChatMetaNode.class) {
return Prefix.builder("stub", 1)
.withMetadata(InheritanceOriginMetadata.KEY, new InheritanceOrigin(
new PermissionHolderIdentifier(HolderType.GROUP, "stub"),
DataType.NORMAL
))
.build();
} else if (clazz == ContextSet.class) {
return ImmutableContextSetImpl.of("stub", "stub");
} else if (clazz == Component.class) {
return Component.text("stub");
} else if (clazz == List.class) {
return ImmutableList.of();
} else if (clazz == Collection.class) {
return ImmutableList.of();
}
Object mock;
if (clazz == LuckPermsPlugin.class) {
mock = mock(clazz, Answers.RETURNS_DEEP_STUBS);
} else {
mock = mock(clazz, Answers.RETURNS_SMART_NULLS);
}
if (mock instanceof LuckPermsBootstrap) {
LuckPermsBootstrap bootstrap = (LuckPermsBootstrap) mock;
lenient().when(bootstrap.getType()).thenReturn(Platform.Type.BUKKIT);
lenient().when(bootstrap.getStartupTime()).thenReturn(Instant.now());
} else if (mock instanceof LuckPermsPlugin) {
LuckPermsPlugin plugin = (LuckPermsPlugin) mock;
LuckPermsBootstrap bootstrap = (LuckPermsBootstrap) mockArgument(LuckPermsBootstrap.class);
lenient().when(plugin.getBootstrap()).thenReturn(bootstrap);
Storage storage = (Storage) mockArgument(Storage.class);
lenient().when(plugin.getStorage()).thenReturn(storage);
SimpleExtensionManager extManager = (SimpleExtensionManager) mockArgument(SimpleExtensionManager.class);
lenient().when(plugin.getExtensionManager()).thenReturn(extManager);
lenient().when(plugin.getMessagingService()).thenReturn(Optional.empty());
} else if (mock instanceof PermissionHolder) {
PermissionHolder holder = (PermissionHolder) mock;
LuckPermsPlugin plugin = (LuckPermsPlugin) mockArgument(LuckPermsPlugin.class);
lenient().when(holder.getPlugin()).thenReturn(plugin);
lenient().when(holder.getFormattedDisplayName()).thenReturn(Component.text("stub"));
} else if (mock instanceof SimpleExtensionManager) {
SimpleExtensionManager manager = (SimpleExtensionManager) mock;
lenient().when(manager.getLoadedExtensions()).thenReturn(ImmutableList.of());
}
return mock;
}
}
@@ -23,22 +23,39 @@
* SOFTWARE.
*/
package me.lucko.luckperms.standalone;
package me.lucko.luckperms.common.storage;
import me.lucko.luckperms.common.plugin.scheduler.AbstractJavaScheduler;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.implementation.mongodb.MongoStorage;
import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import org.junit.jupiter.api.Tag;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;
import java.util.concurrent.Executor;
@Tag("docker")
public class MongoStorageTest extends AbstractStorageTest {
public class StandaloneSchedulerAdapter extends AbstractJavaScheduler implements SchedulerAdapter {
private final GenericContainer<?> container = new GenericContainer<>(DockerImageName.parse("mongo"))
.withExposedPorts(27017);
public StandaloneSchedulerAdapter(LPStandaloneBootstrap bootstrap) {
super(bootstrap);
@Override
protected StorageImplementation makeStorage(LuckPermsPlugin plugin) throws Exception {
this.container.start();
String host = this.container.getHost();
Integer port = this.container.getFirstMappedPort();
StorageCredentials credentials = new StorageCredentials(
host + ":" + port,
"minecraft",
"",
""
);
return new MongoStorage(plugin, credentials, "", "");
}
@Override
public Executor sync() {
return this.async();
protected void cleanupResources() {
this.container.stop();
}
}
@@ -0,0 +1,63 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.storage;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
import me.lucko.luckperms.common.storage.implementation.rest.RestStorage;
import org.junit.jupiter.api.Tag;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.containers.wait.strategy.WaitAllStrategy;
import org.testcontainers.utility.DockerImageName;
@Tag("docker")
public class RestStorageTest extends AbstractStorageTest {
private final GenericContainer<?> container = new GenericContainer<>(DockerImageName.parse("ghcr.io/luckperms/rest-api"))
.withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger(RestStorageTest.class)))
.withExposedPorts(8080)
.waitingFor(new WaitAllStrategy()
.withStrategy(Wait.forListeningPort())
.withStrategy(Wait.forLogMessage(".*Successfully enabled.*", 1))
);
@Override
protected StorageImplementation makeStorage(LuckPermsPlugin plugin) throws Exception {
this.container.start();
String host = this.container.getHost();
Integer port = this.container.getFirstMappedPort();
return new RestStorage(plugin, "http://" + host + ":" + port + "/", null);
}
@Override
protected void cleanupResources() {
this.container.stop();
}
}
-34
View File
@@ -1,34 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
<property name="severity" value="error"/>
</module>
<module name="TreeWalker">
<module name="FinalLocalVariable"/>
<module name="AvoidStarImport"/>
<module name="Indentation">
<property name="severity" value="ignore"/>
</module>
</module>
<module name="RegexpSingleline">
<property name="format" value="\borg\.junit\.jupiter\.api\.Assertions\.fail\s*\(\s*&quot;Not yet implemented&quot;\s*\)\s*;"/>
<property name="message" value="Remove placeholder fail() and implement the test."/>
<property name="ignoreCase" value="true"/>
<property name="severity" value="warning"/>
</module>
<module name="RegexpSingleline">
<property name="format" value="(?&lt;!\w)fail\s*\(\s*&quot;Not yet implemented&quot;\s*\)\s*;"/>
<property name="message" value="Remove placeholder fail() and implement the test."/>
<property name="severity" value="warning"/>
</module>
</module>
-404
View File
@@ -1,404 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="23">
<profile kind="CodeFormatterProfile" name="TrueOG Network Formatting" version="23">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_permitted_types_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.javadoc_do_not_separate_block_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case_after_arrow" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.align_arrows_in_switch_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow" value="20"/>
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>
+88
View File
@@ -0,0 +1,88 @@
import net.fabricmc.loom.task.RemapJarTask
plugins {
alias(libs.plugins.shadow)
alias(libs.plugins.loom)
}
archivesBaseName = 'luckperms'
repositories {
maven { url 'https://maven.fabricmc.net/' }
}
dependencies {
// https://modmuss50.me/fabric.html
minecraft 'com.mojang:minecraft:1.21.8'
mappings 'net.fabricmc:yarn:1.21.8+build.1:v2'
modImplementation 'net.fabricmc:fabric-loader:0.16.14'
Set<String> apiModules = [
'fabric-api-base',
'fabric-command-api-v2',
'fabric-lifecycle-events-v1',
'fabric-networking-api-v1',
'fabric-entity-events-v1'
]
apiModules.forEach {
modImplementation(fabricApi.module(it, '0.129.0+1.21.8'))
}
include(modImplementation('me.lucko:fabric-permissions-api:0.4.1'))
implementation project(':common')
}
processResources {
inputs.property 'version', project.ext.fullVersion
filesMatching('**/fabric.mod.json') {
expand 'version': project.ext.fullVersion
}
}
shadowJar {
archiveFileName = "luckpermsfabric-${project.ext.fullVersion}-dev.jar"
dependencies {
exclude('net.fabricmc:.*')
include(dependency('net.luckperms:.*'))
include(dependency('me.lucko.luckperms:.*'))
// We don't want to include the mappings in the jar do we?
exclude '/mappings/*'
}
relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
relocate 'okio', 'me.lucko.luckperms.lib.okio'
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
relocate 'org.yaml.snakeyaml', 'me.lucko.luckperms.lib.yaml'
}
task remappedShadowJar(type: RemapJarTask) {
dependsOn tasks.shadowJar
input = tasks.shadowJar.archiveFile
addNestedDependencies = true
archiveFileName = "LuckPerms-Fabric-${project.ext.fullVersion}.jar"
}
tasks.assemble.dependsOn tasks.remappedShadowJar
artifacts {
archives remappedShadowJar
shadow shadowJar
}
@@ -25,20 +25,25 @@
package me.lucko.luckperms.fabric;
import me.lucko.luckperms.common.plugin.scheduler.AbstractJavaScheduler;
import me.lucko.luckperms.common.plugin.scheduler.JavaSchedulerAdapter;
import me.lucko.luckperms.common.sender.Sender;
import java.util.concurrent.Executor;
public class FabricSchedulerAdapter extends AbstractJavaScheduler {
private final Executor sync;
public class FabricSchedulerAdapter extends JavaSchedulerAdapter {
private final Executor syncExecutor;
public FabricSchedulerAdapter(LPFabricBootstrap bootstrap) {
super(bootstrap);
this.sync = r -> bootstrap.getServer().orElseThrow(() -> new IllegalStateException("Server not ready")).submitAndJoin(r);
this.syncExecutor = r -> bootstrap.getServer().orElseThrow(() -> new IllegalStateException("Server not ready")).submitAndJoin(r);
}
public void sync(Runnable task) {
this.syncExecutor.execute(task);
}
@Override
public Executor sync() {
return this.sync;
public void sync(Sender ctx, Runnable task) {
this.syncExecutor.execute(task);
}
}
@@ -30,7 +30,6 @@ import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender;
import me.lucko.luckperms.common.plugin.logging.Log4jPluginLogger;
import me.lucko.luckperms.common.plugin.logging.PluginLogger;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import net.fabricmc.api.DedicatedServerModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.loader.api.FabricLoader;
@@ -73,7 +72,7 @@ public final class LPFabricBootstrap implements LuckPermsBootstrap, DedicatedSer
/**
* A scheduler adapter for the platform
*/
private final SchedulerAdapter schedulerAdapter;
private final FabricSchedulerAdapter schedulerAdapter;
/**
* The plugin class path appender
@@ -116,7 +115,7 @@ public final class LPFabricBootstrap implements LuckPermsBootstrap, DedicatedSer
}
@Override
public SchedulerAdapter getScheduler() {
public FabricSchedulerAdapter getScheduler() {
return this.schedulerAdapter;
}
@@ -80,7 +80,7 @@ public class FabricAutoOpListener implements LuckPermsEventListener {
if (callerIsSync) {
setOp(player, value);
} else {
this.plugin.getBootstrap().getScheduler().executeSync(() -> setOp(player, value));
this.plugin.getBootstrap().getScheduler().sync(() -> setOp(player, value));
}
}
@@ -35,6 +35,7 @@ import net.luckperms.api.event.EventBus;
import net.luckperms.api.event.context.ContextUpdateEvent;
import net.luckperms.api.event.group.GroupDataRecalculateEvent;
import net.luckperms.api.event.user.UserDataRecalculateEvent;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import java.util.UUID;
@@ -89,14 +90,15 @@ public class FabricCommandListUpdater implements LuckPermsEventListener {
// Called when the buffer times out.
private void sendUpdate(UUID uniqueId) {
this.plugin.getBootstrap().getScheduler().sync()
.execute(() -> this.plugin.getBootstrap().getPlayer(uniqueId)
.ifPresent(player -> this.plugin.getBootstrap().getServer()
.ifPresent(server -> {
server.getPlayerManager().sendCommandTree(player);
})
)
);
this.plugin.getBootstrap().getScheduler().sync(() -> {
ServerPlayerEntity player = this.plugin.getBootstrap().getPlayer(uniqueId).orElse(null);
if (player != null) {
MinecraftServer server = player.getServer();
if (server != null) {
server.getPlayerManager().sendCommandTree(player);
}
}
});
}
private final class SendBuffer extends BufferedRequest<Void> {
@@ -131,9 +131,7 @@ public class FabricConnectionListener extends AbstractConnectionListener {
}
private void onDisconnect(ServerPlayNetworkHandler netHandler, MinecraftServer server) {
if (!server.isStopped()) {
handleDisconnect(netHandler.player.getUuid());
}
handleDisconnect(netHandler.player.getUuid());
}
}
+56
View File
@@ -0,0 +1,56 @@
plugins {
alias(libs.plugins.blossom)
alias(libs.plugins.shadow)
alias(libs.plugins.forgegradle)
}
sourceCompatibility = 21
targetCompatibility = 21
blossom {
replaceTokenIn 'src/main/java/me/lucko/luckperms/forge/LPForgeBootstrap.java'
replaceToken '@version@', project.ext.fullVersion
}
minecraft {
mappings channel: 'official', version: minecraftVersion
}
dependencies {
minecraft "net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}"
annotationProcessor 'net.minecraftforge:eventbus-validator:7.0-beta.7'
implementation project(':common')
compileOnly project(':common:loader-utils')
}
shadowJar {
archiveFileName = "luckperms-forge.jarinjar"
dependencies {
include(dependency('me.lucko.luckperms:.*'))
}
relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
relocate 'okio', 'me.lucko.luckperms.lib.okio'
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
relocate 'org.yaml.snakeyaml', 'me.lucko.luckperms.lib.yaml'
}
artifacts {
archives shadowJar
}
+59
View File
@@ -0,0 +1,59 @@
plugins {
alias(libs.plugins.shadow)
alias(libs.plugins.forgegradle)
id("java-library")
}
sourceCompatibility = 21
targetCompatibility = 21
minecraft {
mappings channel: 'official', version: minecraftVersion
}
dependencies {
minecraft "net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}"
implementation project(':api')
implementation project(':common:loader-utils')
}
build {
dependsOn(":forge:build")
}
jar {
manifest {
attributes(
'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
'Implementation-Title': 'LuckPerms',
'Implementation-Vendor': 'LuckPerms',
'Implementation-Version': project.ext.fullVersion,
'Specification-Title': 'luckperms',
'Specification-Vendor': 'LuckPerms',
'Specification-Version': '1'
)
}
}
processResources {
filesMatching('META-INF/mods.toml') {
expand 'version': project.ext.fullVersion
}
}
shadowJar {
archiveFileName = "LuckPerms-Forge-${project.ext.fullVersion}.jar"
from {
project(':forge').tasks.shadowJar.archiveFile
}
dependencies {
include(dependency('net.luckperms:.*'))
include(dependency('me.lucko.luckperms:.*'))
}
}
artifacts {
archives shadowJar
}
@@ -25,21 +25,26 @@
package me.lucko.luckperms.forge;
import me.lucko.luckperms.common.plugin.scheduler.AbstractJavaScheduler;
import me.lucko.luckperms.common.plugin.scheduler.JavaSchedulerAdapter;
import me.lucko.luckperms.common.sender.Sender;
import java.util.concurrent.Executor;
public class ForgeSchedulerAdapter extends AbstractJavaScheduler {
private final Executor sync;
public class ForgeSchedulerAdapter extends JavaSchedulerAdapter {
private final Executor syncExecutor;
public ForgeSchedulerAdapter(LPForgeBootstrap bootstrap) {
super(bootstrap);
this.sync = r -> bootstrap.getServer().orElseThrow(() -> new IllegalStateException("Server not ready")).executeBlocking(r);
this.syncExecutor = r -> bootstrap.getServer().orElseThrow(() -> new IllegalStateException("Server not ready")).executeBlocking(r);
}
public void sync(Runnable task) {
this.syncExecutor.execute(task);
}
@Override
public Executor sync() {
return this.sync;
public void sync(Sender ctx, Runnable task) {
this.syncExecutor.execute(task);
}
}
@@ -33,7 +33,6 @@ import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender;
import me.lucko.luckperms.common.plugin.classpath.JarInJarClassPathAppender;
import me.lucko.luckperms.common.plugin.logging.Log4jPluginLogger;
import me.lucko.luckperms.common.plugin.logging.PluginLogger;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import net.luckperms.api.platform.Platform;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
@@ -82,7 +81,7 @@ public final class LPForgeBootstrap implements LuckPermsBootstrap, LoaderBootstr
/**
* A scheduler adapter for the platform
*/
private final SchedulerAdapter schedulerAdapter;
private final ForgeSchedulerAdapter schedulerAdapter;
/**
* The plugin class path appender
@@ -134,7 +133,7 @@ public final class LPForgeBootstrap implements LuckPermsBootstrap, LoaderBootstr
}
@Override
public SchedulerAdapter getScheduler() {
public ForgeSchedulerAdapter getScheduler() {
return this.schedulerAdapter;
}
@@ -80,7 +80,7 @@ public class ForgeAutoOpListener implements LuckPermsEventListener {
if (callerIsSync) {
setOp(player, value);
} else {
this.plugin.getBootstrap().getScheduler().executeSync(() -> setOp(player, value));
this.plugin.getBootstrap().getScheduler().sync(() -> setOp(player, value));
}
}
@@ -91,13 +91,14 @@ public class ForgeCommandListUpdater implements LuckPermsEventListener {
// Called when the buffer times out.
private void sendUpdate(UUID uniqueId) {
this.plugin.getBootstrap().getScheduler().sync().execute(() -> {
this.plugin.getBootstrap().getPlayer(uniqueId).ifPresent(player -> {
this.plugin.getBootstrap().getScheduler().sync(() -> {
ServerPlayer player = this.plugin.getBootstrap().getPlayer(uniqueId).orElse(null);
if (player != null) {
MinecraftServer server = player.getServer();
if (server != null) {
server.getPlayerList().sendPlayerPermissionLevel(player);
}
});
}
});
}
+62
View File
@@ -0,0 +1,62 @@
plugins {
alias(libs.plugins.blossom)
alias(libs.plugins.shadow)
alias(libs.plugins.moddevgradle)
}
sourceCompatibility = 21
targetCompatibility = 21
Configuration shade = configurations.create('shade')
configurations.implementation {
extendsFrom configurations.shade
}
blossom {
replaceTokenIn 'src/main/java/me/lucko/luckperms/neoforge/LPNeoForgeBootstrap.java'
replaceToken '@version@', project.ext.fullVersion
}
neoForge {
version = project.neoForgeVersion
validateAccessTransformers = true
}
dependencies {
add('shade', project(':common'))
compileOnly project(':common:loader-utils')
}
shadowJar {
archiveFileName = "luckperms-neoforge.jarinjar"
configurations = [shade]
dependencies {
include(dependency('me.lucko.luckperms:.*'))
}
relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
relocate 'okio', 'me.lucko.luckperms.lib.okio'
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
relocate 'org.yaml.snakeyaml', 'me.lucko.luckperms.lib.yaml'
}
artifacts {
archives shadowJar
}
+92
View File
@@ -0,0 +1,92 @@
import net.neoforged.moddevgradle.internal.RunGameTask
import java.nio.file.Files
import java.nio.file.StandardCopyOption
plugins {
alias(libs.plugins.shadow)
alias(libs.plugins.moddevgradle)
id("java-library")
}
sourceCompatibility = 21
targetCompatibility = 21
neoForge {
version = project.neoForgeVersion
validateAccessTransformers = true
runs {
client {
client()
//mods.set(new HashSet()) // Work around classpath issues by using the production jar for dev runs
}
server {
server()
//mods.set(new HashSet()) // Work around classpath issues by using the production jar for dev runs
}
}
}
// Work around classpath issues by using the production jar for dev runs
tasks.withType(RunGameTask).configureEach {
dependsOn(tasks.shadowJar)
doFirst {
File jar = file("run/mods/main.jar")
jar.parentFile.mkdirs()
Files.copy(tasks.shadowJar.archiveFile.get().asFile.toPath(), jar.toPath(), StandardCopyOption.REPLACE_EXISTING)
}
}
Configuration shade = configurations.create('shade')
configurations.implementation {
extendsFrom configurations.shade
}
dependencies {
add('shade', project(':api'))
add('shade', project(':common:loader-utils'))
}
build {
dependsOn(":neoforge:build")
}
jar {
manifest {
attributes(
'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
'Implementation-Title': 'LuckPerms',
'Implementation-Vendor': 'LuckPerms',
'Implementation-Version': project.ext.fullVersion,
'Specification-Title': 'luckperms',
'Specification-Vendor': 'LuckPerms',
'Specification-Version': '1'
)
}
}
processResources {
filesMatching('META-INF/neoforge.mods.toml') {
expand 'version': project.ext.fullVersion
}
}
shadowJar {
archiveFileName = "LuckPerms-NeoForge-${project.ext.fullVersion}.jar"
configurations = [shade]
from {
project(':neoforge').tasks.shadowJar.archiveFile
}
dependencies {
include(dependency('net.luckperms:.*'))
include(dependency('me.lucko.luckperms:.*'))
}
}
artifacts {
archives shadowJar
}
@@ -80,7 +80,7 @@ public final class LPNeoForgeBootstrap implements LuckPermsBootstrap, LoaderBoot
/**
* A scheduler adapter for the platform
*/
private final SchedulerAdapter schedulerAdapter;
private final NeoForgeSchedulerAdapter schedulerAdapter;
/**
* The plugin class path appender
@@ -133,7 +133,7 @@ public final class LPNeoForgeBootstrap implements LuckPermsBootstrap, LoaderBoot
}
@Override
public SchedulerAdapter getScheduler() {
public NeoForgeSchedulerAdapter getScheduler() {
return this.schedulerAdapter;
}
@@ -25,21 +25,26 @@
package me.lucko.luckperms.neoforge;
import me.lucko.luckperms.common.plugin.scheduler.AbstractJavaScheduler;
import me.lucko.luckperms.common.plugin.scheduler.JavaSchedulerAdapter;
import me.lucko.luckperms.common.sender.Sender;
import java.util.concurrent.Executor;
public class NeoForgeSchedulerAdapter extends AbstractJavaScheduler {
private final Executor sync;
public class NeoForgeSchedulerAdapter extends JavaSchedulerAdapter {
private final Executor syncExecutor;
public NeoForgeSchedulerAdapter(LPNeoForgeBootstrap bootstrap) {
super(bootstrap);
this.sync = r -> bootstrap.getServer().orElseThrow(() -> new IllegalStateException("Server not ready")).executeBlocking(r);
this.syncExecutor = r -> bootstrap.getServer().orElseThrow(() -> new IllegalStateException("Server not ready")).executeBlocking(r);
}
public void sync(Runnable task) {
this.syncExecutor.execute(task);
}
@Override
public Executor sync() {
return this.sync;
public void sync(Sender ctx, Runnable task) {
this.syncExecutor.execute(task);
}
}
@@ -80,7 +80,7 @@ public class NeoForgeAutoOpListener implements LuckPermsEventListener {
if (callerIsSync) {
setOp(player, value);
} else {
this.plugin.getBootstrap().getScheduler().executeSync(() -> setOp(player, value));
this.plugin.getBootstrap().getScheduler().sync(() -> setOp(player, value));
}
}
@@ -91,14 +91,15 @@ public class NeoForgeCommandListUpdater implements LuckPermsEventListener {
// Called when the buffer times out.
private void sendUpdate(UUID uniqueId) {
this.plugin.getBootstrap().getScheduler().sync().execute(() -> {
this.plugin.getBootstrap().getPlayer(uniqueId).ifPresent(player -> {
this.plugin.getBootstrap().getScheduler().sync((() -> {
ServerPlayer player = this.plugin.getBootstrap().getPlayer(uniqueId).orElse(null);
if (player != null) {
MinecraftServer server = player.getServer();
if (server != null) {
server.getPlayerList().sendPlayerPermissionLevel(player);
}
});
});
}
}));
}
private final class SendBuffer extends BufferedRequest<Void> {
+45
View File
@@ -0,0 +1,45 @@
plugins {
alias(libs.plugins.shadow)
}
repositories {
maven { url 'https://repo.opencollab.dev/main/' }
}
dependencies {
implementation project(':common')
compileOnly project(':common:loader-utils')
compileOnly 'cn.nukkit:nukkit:1.0-SNAPSHOT'
}
shadowJar {
archiveFileName = 'luckperms-nukkit.jarinjar'
dependencies {
include(dependency('me.lucko.luckperms:.*'))
}
relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
relocate 'okio', 'me.lucko.luckperms.lib.okio'
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
}
artifacts {
archives shadowJar
}
+32
View File
@@ -0,0 +1,32 @@
plugins {
alias(libs.plugins.shadow)
}
repositories {
maven { url 'https://repo.opencollab.dev/main/' }
}
dependencies {
compileOnly 'cn.nukkit:nukkit:1.0-SNAPSHOT'
implementation project(':api')
implementation project(':common:loader-utils')
}
processResources {
filesMatching('plugin.yml') {
expand 'pluginVersion': project.ext.fullVersion
}
}
shadowJar {
archiveFileName = "LuckPerms-Nukkit-${project.ext.fullVersion}.jar"
from {
project(':nukkit').tasks.shadowJar.archiveFile
}
}
artifacts {
archives shadowJar
}
@@ -202,11 +202,11 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
// Load any online users (in the case of a reload)
for (Player player : this.bootstrap.getServer().getOnlinePlayers().values()) {
this.bootstrap.getScheduler().executeAsync(() -> {
this.bootstrap.getScheduler().async(() -> {
try {
User user = this.connectionListener.loadUser(player.getUniqueId(), player.getName());
if (user != null) {
this.bootstrap.getScheduler().executeSync(() -> {
this.bootstrap.getScheduler().sync(() -> {
try {
LuckPermsPermissible lpPermissible = new LuckPermsPermissible(player, user, this);
PermissibleInjector.inject(player, lpPermissible);
@@ -25,22 +25,27 @@
package me.lucko.luckperms.nukkit;
import me.lucko.luckperms.common.plugin.scheduler.AbstractJavaScheduler;
import me.lucko.luckperms.common.plugin.scheduler.JavaSchedulerAdapter;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import me.lucko.luckperms.common.sender.Sender;
import java.util.concurrent.Executor;
public class NukkitSchedulerAdapter extends AbstractJavaScheduler implements SchedulerAdapter {
private final Executor sync;
public class NukkitSchedulerAdapter extends JavaSchedulerAdapter implements SchedulerAdapter {
private final Executor syncExecutor;
public NukkitSchedulerAdapter(LPNukkitBootstrap bootstrap) {
super(bootstrap);
this.sync = r -> bootstrap.getServer().getScheduler().scheduleTask(bootstrap.getLoader(), r, false);
this.syncExecutor = r -> bootstrap.getServer().getScheduler().scheduleTask(bootstrap.getLoader(), r, false);
}
public void sync(Runnable task) {
this.syncExecutor.execute(task);
}
@Override
public Executor sync() {
return this.sync;
public void sync(Sender ctx, Runnable task) {
this.syncExecutor.execute(task);
}
}
+45
View File
@@ -0,0 +1,45 @@
pluginManagement {
repositories {
gradlePluginPortal()
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
maven {
name = 'Forge'
url = 'https://maven.minecraftforge.net/'
}
}
}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version("0.8.0")
}
rootProject.name = 'luckperms'
include (
'api',
'common',
'common:loader-utils',
'bukkit',
'bukkit:loader',
'bukkit-legacy',
'bukkit-legacy:loader',
'bungee',
'bungee:loader',
'fabric',
'neoforge',
'neoforge:loader',
'forge',
'forge:loader',
'nukkit',
'nukkit:loader',
'sponge',
'sponge:loader',
'sponge:sponge-service',
'sponge:sponge-service-proxy',
'velocity',
'standalone',
'standalone:loader',
'standalone:app'
)
-7
View File
@@ -1,7 +0,0 @@
rootProject.name = "LuckPerms-OG"
include(":api", ":common", ":common:loader-utils", ":bukkit", ":bukkit:loader")
project(":common:loader-utils").projectDir = file("common/loader-utils")
project(":bukkit:loader").projectDir = file("bukkit/loader")
+62
View File
@@ -0,0 +1,62 @@
plugins {
alias(libs.plugins.shadow)
}
sourceCompatibility = 21
targetCompatibility = 21
repositories {
maven { url 'https://repo.spongepowered.org/repository/maven-public/' }
}
dependencies {
implementation project(':common')
implementation project(':sponge:sponge-service')
implementation project(':sponge:sponge-service-proxy')
compileOnly project(':common:loader-utils')
compileOnly('org.spongepowered:spongeapi:12.0.0') {
exclude(module: 'configurate-core')
exclude(module: 'configurate-hocon')
exclude(module: 'configurate-gson')
exclude(module: 'configurate-yaml')
}
compileOnly 'com.google.guava:guava:33.3.1-jre'
}
processResources {
filesMatching('META-INF/sponge_plugins.json') {
expand 'pluginVersion': project.ext.fullVersion
}
}
shadowJar {
archiveFileName = 'luckperms-sponge.jarinjar'
dependencies {
include(dependency('me.lucko.luckperms:.*'))
}
//relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
relocate 'okio', 'me.lucko.luckperms.lib.okio'
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
}
artifacts {
archives shadowJar
}
+35
View File
@@ -0,0 +1,35 @@
plugins {
alias(libs.plugins.shadow)
}
sourceCompatibility = 21
targetCompatibility = 21
repositories {
maven { url 'https://repo.spongepowered.org/repository/maven-public/' }
}
dependencies {
compileOnly 'org.spongepowered:spongeapi:12.0.0'
implementation project(':api')
implementation project(':common:loader-utils')
}
processResources {
filesMatching('META-INF/sponge_plugins.json') {
expand 'pluginVersion': project.ext.fullVersion
}
}
shadowJar {
archiveFileName = "LuckPerms-Sponge-${project.ext.fullVersion}.jar"
from {
project(':sponge').tasks.shadowJar.archiveFile
}
}
artifacts {
archives shadowJar
}
+18
View File
@@ -0,0 +1,18 @@
repositories {
maven { url 'https://repo.spongepowered.org/repository/maven-public/' }
}
sourceCompatibility = 21
targetCompatibility = 21
dependencies {
implementation project(':common')
implementation project(':sponge:sponge-service')
compileOnly('org.spongepowered:spongeapi:12.0.0') {
exclude(module: 'configurate-core')
exclude(module: 'configurate-hocon')
exclude(module: 'configurate-gson')
exclude(module: 'configurate-yaml')
}
}
+18
View File
@@ -0,0 +1,18 @@
repositories {
maven { url 'https://repo.spongepowered.org/repository/maven-public/' }
}
sourceCompatibility = 21
targetCompatibility = 21
dependencies {
implementation project(':common')
compileOnly('org.spongepowered:spongeapi:12.0.0') {
exclude(module: 'configurate-core')
exclude(module: 'configurate-hocon')
exclude(module: 'configurate-gson')
exclude(module: 'configurate-yaml')
}
}
@@ -28,6 +28,7 @@ package me.lucko.luckperms.sponge;
import com.google.common.base.Suppliers;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerTask;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.util.Iterators;
import org.spongepowered.api.Game;
import org.spongepowered.api.scheduler.ScheduledTask;
@@ -64,20 +65,24 @@ public class SpongeSchedulerAdapter implements SchedulerAdapter {
this.sync = Suppliers.memoize(() -> getSyncScheduler().executor(this.pluginContainer));
}
public Scheduler getSyncScheduler() {
return this.game.server().scheduler();
}
public void sync(Runnable task) {
this.sync.get().execute(task);
}
@Override
public void sync(Sender ctx, Runnable task) {
this.sync.get().execute(task);
}
@Override
public Executor async() {
return this.async;
}
@Override
public Executor sync() {
return this.sync.get();
}
public Scheduler getSyncScheduler() {
return this.game.server().scheduler();
}
private SchedulerTask submitAsyncTask(Runnable runnable, Consumer<Task.Builder> config) {
Task.Builder builder = Task.builder();
config.accept(builder);
@@ -79,7 +79,7 @@ public class SpongeCommandListUpdater implements LuckPermsEventListener {
// Called when the buffer times out.
private void sendUpdate(UUID uniqueId) {
this.plugin.getBootstrap().getScheduler().sync().execute(() -> {
this.plugin.getBootstrap().getScheduler().sync(() -> {
ServerPlayer player = this.plugin.getBootstrap().getPlayer(uniqueId).orElse(null);
if (player != null) {
CommandManager commandManager = this.plugin.getBootstrap().getGame().server().commandManager();
@@ -246,7 +246,7 @@ public class LuckPermsService implements LPPermissionService {
@Override
public void fireUpdateEvent(LPSubjectData subjectData) {
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
this.plugin.getBootstrap().getScheduler().async(() -> {
SubjectDataUpdateEvent event = new SubjectDataUpdateEventImpl(this.plugin, subjectData);
this.plugin.getBootstrap().getGame().eventManager().post(event);
});
+56
View File
@@ -0,0 +1,56 @@
plugins {
alias(libs.plugins.blossom)
id("java-library")
}
sourceCompatibility = 17
targetCompatibility = 17
dependencies {
implementation project(':api')
api 'org.apache.logging.log4j:log4j-core:2.17.2'
api 'org.apache.logging.log4j:log4j-slf4j-impl:2.17.2'
api 'net.minecrell:terminalconsoleappender:1.3.0'
api 'org.jline:jline-terminal-jansi:3.20.0'
api 'com.google.code.gson:gson:2.13.1'
api 'com.google.guava:guava:33.4.8-jre'
api 'io.netty:netty-all:4.2.1.Final'
api('net.kyori:adventure-api:4.21.0') {
exclude(module: 'adventure-bom')
exclude(module: 'checker-qual')
exclude(module: 'annotations')
}
api('net.kyori:adventure-text-serializer-gson:4.21.0') {
exclude(module: 'adventure-bom')
exclude(module: 'adventure-api')
exclude(module: 'gson')
}
api('net.kyori:adventure-text-serializer-legacy:4.21.0') {
exclude(module: 'adventure-bom')
exclude(module: 'adventure-api')
}
api('net.kyori:adventure-text-serializer-plain:4.21.0') {
exclude(module: 'adventure-bom')
exclude(module: 'adventure-api')
}
api('net.kyori:adventure-text-minimessage:4.21.0') {
exclude(module: 'adventure-bom')
exclude(module: 'adventure-api')
}
api('net.kyori:adventure-text-serializer-ansi:4.21.0') {
exclude(module: 'adventure-bom')
exclude(module: 'adventure-api')
exclude(module: 'annotations')
}
api('net.kyori:ansi:1.1.1') {
exclude(module: 'annotations')
}
}
blossom {
replaceTokenIn('src/main/java/me/lucko/luckperms/standalone/app/LuckPermsApplication.java')
replaceToken '@version@', project.ext.fullVersion
}
+85
View File
@@ -0,0 +1,85 @@
plugins {
alias(libs.plugins.shadow)
id("jacoco")
id("jacoco-report-aggregation")
}
sourceCompatibility = 17
targetCompatibility = 17
test {
useJUnitPlatform {
if (!project.hasProperty('dockerTests')) {
excludeTags 'docker'
}
}
systemProperty('net.kyori.ansi.colorLevel', 'indexed16')
}
jacocoTestReport {
dependsOn test
}
dependencies {
implementation project(':common')
compileOnly project(':common:loader-utils')
compileOnly project(':standalone:app')
testImplementation 'org.junit.jupiter:junit-jupiter:5.13.0'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation 'org.testcontainers:junit-jupiter:1.21.1'
testImplementation 'org.mockito:mockito-core:5.18.0'
testImplementation 'org.mockito:mockito-junit-jupiter:5.18.0'
testImplementation 'org.awaitility:awaitility:4.3.0'
testImplementation 'com.zaxxer:HikariCP:6.3.0'
testImplementation 'redis.clients:jedis:5.2.0'
testImplementation 'io.nats:jnats:2.21.1'
testImplementation 'com.rabbitmq:amqp-client:5.25.0'
testImplementation 'org.postgresql:postgresql:42.7.6'
testImplementation 'com.h2database:h2:2.1.214'
testImplementation 'org.xerial:sqlite-jdbc:3.49.1.0'
testImplementation 'com.mysql:mysql-connector-j:9.3.0'
testImplementation 'org.mariadb.jdbc:mariadb-java-client:3.5.2'
testImplementation 'org.mongodb:mongodb-driver-legacy:5.5.0'
testImplementation 'me.lucko.configurate:configurate-toml:3.7'
testImplementation 'org.spongepowered:configurate-yaml:3.7.3'
testImplementation 'org.spongepowered:configurate-hocon:3.7.3'
testImplementation 'org.yaml:snakeyaml:1.22'
testImplementation 'net.luckperms:rest-api-java-client:0.1'
testImplementation project(':standalone:app')
testImplementation project(':common:loader-utils')
}
shadowJar {
archiveFileName = 'luckperms-standalone.jarinjar'
dependencies {
include(dependency('me.lucko.luckperms:.*'))
}
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
relocate 'okio', 'me.lucko.luckperms.lib.okio'
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
relocate 'org.yaml.snakeyaml', 'me.lucko.luckperms.lib.yaml'
}
artifacts {
archives shadowJar
}
+37
View File
@@ -0,0 +1,37 @@
import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer
plugins {
alias(libs.plugins.shadow)
id("application")
}
dependencies {
implementation project(':api')
implementation project(':common:loader-utils')
implementation project(':standalone:app')
}
sourceCompatibility = 17
targetCompatibility = 17
application {
mainClass = 'me.lucko.luckperms.standalone.loader.StandaloneLoader'
}
processResources {
include '*.xml'
}
shadowJar {
archiveFileName = "LuckPerms-Standalone-${project.ext.fullVersion}.jar"
from {
project(':standalone').tasks.shadowJar.archiveFile
}
transform(Log4j2PluginsCacheFileTransformer)
}
artifacts {
archives shadowJar
}
@@ -32,6 +32,8 @@ import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender;
import me.lucko.luckperms.common.plugin.classpath.JarInJarClassPathAppender;
import me.lucko.luckperms.common.plugin.logging.Log4jPluginLogger;
import me.lucko.luckperms.common.plugin.logging.PluginLogger;
import me.lucko.luckperms.common.plugin.scheduler.JavaSchedulerAdapter;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import me.lucko.luckperms.standalone.app.LuckPermsApplication;
import net.luckperms.api.platform.Platform;
@@ -51,7 +53,7 @@ public class LPStandaloneBootstrap implements LuckPermsBootstrap, LoaderBootstra
private final LuckPermsApplication loader;
private final PluginLogger logger;
private final StandaloneSchedulerAdapter schedulerAdapter;
private final SchedulerAdapter schedulerAdapter;
private final ClassPathAppender classPathAppender;
private final LPStandalonePlugin plugin;
@@ -63,7 +65,7 @@ public class LPStandaloneBootstrap implements LuckPermsBootstrap, LoaderBootstra
this.loader = loader;
this.logger = new Log4jPluginLogger(LuckPermsApplication.LOGGER);
this.schedulerAdapter = new StandaloneSchedulerAdapter(this);
this.schedulerAdapter = new JavaSchedulerAdapter(this);
this.classPathAppender = new JarInJarClassPathAppender(getClass().getClassLoader());
this.plugin = new LPStandalonePlugin(this);
}
@@ -73,7 +75,7 @@ public class LPStandaloneBootstrap implements LuckPermsBootstrap, LoaderBootstra
this.loader = loader;
this.logger = new Log4jPluginLogger(LuckPermsApplication.LOGGER);
this.schedulerAdapter = new StandaloneSchedulerAdapter(this);
this.schedulerAdapter = new JavaSchedulerAdapter(this);
this.classPathAppender = classPathAppender;
this.plugin = createTestPlugin();
}
@@ -96,7 +98,7 @@ public class LPStandaloneBootstrap implements LuckPermsBootstrap, LoaderBootstra
}
@Override
public StandaloneSchedulerAdapter getScheduler() {
public SchedulerAdapter getScheduler() {
return this.schedulerAdapter;
}
+53
View File
@@ -0,0 +1,53 @@
plugins {
alias(libs.plugins.blossom)
alias(libs.plugins.shadow)
}
repositories {
maven { url 'https://repo.papermc.io/repository/maven-public/' }
}
dependencies {
implementation project(':common')
compileOnly 'com.velocitypowered:velocity-api:3.1.1'
annotationProcessor 'com.velocitypowered:velocity-api:3.1.1'
}
blossom {
replaceTokenIn('src/main/java/me/lucko/luckperms/velocity/LPVelocityBootstrap.java')
replaceToken '@version@', project.ext.fullVersion
}
shadowJar {
archiveFileName = "LuckPerms-Velocity-${project.ext.fullVersion}.jar"
dependencies {
include(dependency('net.luckperms:.*'))
include(dependency('me.lucko.luckperms:.*'))
}
relocate 'net.kyori.adventure', 'me.lucko.luckperms.lib.adventure'
relocate 'net.kyori.event', 'me.lucko.luckperms.lib.eventbus'
relocate 'com.github.benmanes.caffeine', 'me.lucko.luckperms.lib.caffeine'
relocate 'okio', 'me.lucko.luckperms.lib.okio'
relocate 'okhttp3', 'me.lucko.luckperms.lib.okhttp3'
relocate 'net.bytebuddy', 'me.lucko.luckperms.lib.bytebuddy'
relocate 'me.lucko.commodore', 'me.lucko.luckperms.lib.commodore'
relocate 'org.mariadb.jdbc', 'me.lucko.luckperms.lib.mariadb'
relocate 'com.mysql', 'me.lucko.luckperms.lib.mysql'
relocate 'org.postgresql', 'me.lucko.luckperms.lib.postgresql'
relocate 'com.zaxxer.hikari', 'me.lucko.luckperms.lib.hikari'
relocate 'com.mongodb', 'me.lucko.luckperms.lib.mongodb'
relocate 'org.bson', 'me.lucko.luckperms.lib.bson'
relocate 'redis.clients.jedis', 'me.lucko.luckperms.lib.jedis'
relocate 'io.nats.client', 'me.lucko.luckperms.lib.nats'
relocate 'com.rabbitmq', 'me.lucko.luckperms.lib.rabbitmq'
relocate 'org.apache.commons.pool2', 'me.lucko.luckperms.lib.commonspool2'
relocate 'ninja.leaping.configurate', 'me.lucko.luckperms.lib.configurate'
relocate 'org.yaml.snakeyaml', 'me.lucko.luckperms.lib.yaml'
}
artifacts {
archives shadowJar
}
@@ -52,11 +52,6 @@ public class VelocitySchedulerAdapter implements SchedulerAdapter {
return this.executor;
}
@Override
public Executor sync() {
return this.executor;
}
@Override
public SchedulerTask asyncLater(Runnable task, long delay, TimeUnit unit) {
ScheduledTask t = this.bootstrap.getProxy().getScheduler().buildTask(this.bootstrap, task)
@@ -78,7 +78,7 @@ public class VelocityConnectionListener extends AbstractConnectionListener {
this.plugin.getLogger().info("Processing pre-login for " + p.getUniqueId() + " - " + p.getUsername());
}
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
this.plugin.getBootstrap().getScheduler().async(() -> {
/* Actually process the login for the connection.
We do this here to delay the login until the data is ready.
If the login gets cancelled later on, then this will be cleaned up.
@@ -90,7 +90,7 @@ public class PluginMessageMessenger extends AbstractPluginMessageMessenger {
if (handleIncomingMessage(buf)) {
// Forward to other servers
this.plugin.getBootstrap().getScheduler().executeAsync(() -> sendOutgoingMessage(buf));
this.plugin.getBootstrap().getScheduler().async(() -> sendOutgoingMessage(buf));
}
}
}