diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index abe29982..6380a7ae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,39 +1,52 @@ name: Build -on: - release: - types: [published] - workflow_dispatch: +on: [push, pull_request] jobs: build: - runs-on: ubuntu-latest + permissions: + contents: read steps: - - uses: actions/checkout@v3 - - name: Set up JDK - uses: actions/setup-java@v3 - with: - java-version: '21' - distribution: 'temurin' - cache: maven - server-id: central - server-username: CENTRAL_USERNAME - server-password: CENTRAL_TOKEN - gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} - gpg-passphrase: GPG_PASSPHRASE - - - name: Initialize Paper NMS - run: for file in $(grep -l 'paper-nms' $(find -name 'pom.xml')); do mvn -B paper-nms:init --file "$file"; done - - - name: Build the dependencies of the api - run: mvn -B install --file pom.xml -pl '!api' - - - name: Build and deploy the api - working-directory: ./api - run: mvn -B deploy --file pom.xml - env: - CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }} - CENTRAL_TOKEN: ${{ secrets.CENTRAL_TOKEN }} - GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + - uses: actions/checkout@v4 + + - name: Validate Gradle wrapper + uses: gradle/actions/wrapper-validation@v4 + + - name: Set up JDK 21 and 25 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: | + 21 + 25 + cache: gradle + + - name: Build with Gradle + run: chmod +x gradlew && ./gradlew shadowJar -x test --no-daemon + + - name: Upload SignGUI jar + uses: actions/upload-artifact@v4 + with: + name: signgui-build + path: build/libs/signgui-*.jar + if-no-files-found: error + + - name: Publish snapshot to Reposilite + if: github.event_name == 'push' + run: | + VERSION=$(./gradlew -q printVersion) + echo "Project version: $VERSION" + if [[ "$VERSION" != *-SNAPSHOT ]]; then + echo "Not a SNAPSHOT version — skipping snapshot publish." + exit 0 + fi + if [ -z "${REPOSILITE_USER}" ] || [ -z "${REPOSILITE_TOKEN}" ]; then + echo "Missing REPOSILITE_USER / REPOSILITE_TOKEN secrets." + exit 1 + fi + ./gradlew publishSnapshot -x test --no-daemon + env: + REPOSILITE_USER: ${{ secrets.REPOSILITE_USER }} + REPOSILITE_TOKEN: ${{ secrets.REPOSILITE_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..75546e26 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,72 @@ +name: Release + +on: + workflow_dispatch: + inputs: + tag: + description: "Git tag to create/publish (e.g. v2.6.1). Leave empty to use project version." + required: false + default: "" + +permissions: + contents: write + +jobs: + release: + name: Publish Release + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Validate Gradle wrapper + uses: gradle/actions/wrapper-validation@v4 + + - name: Set up JDK 21 and 25 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: | + 21 + 25 + cache: gradle + + - name: Resolve version / tag + id: meta + run: | + PROJECT_VERSION="$(./gradlew -q printVersion)" + TAG_INPUT="${{ github.event.inputs.tag }}" + if [ -n "$TAG_INPUT" ]; then + TAG="$TAG_INPUT" + else + TAG="v${PROJECT_VERSION}" + fi + echo "version=${PROJECT_VERSION}" >> "$GITHUB_OUTPUT" + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + echo "Resolved tag=${TAG} version=${PROJECT_VERSION}" + + - name: Build publishable artifacts + run: chmod +x gradlew && ./gradlew clean shadowJar -x test --no-daemon + + - name: Publish release to Reposilite + run: | + if [ -z "${REPOSILITE_USER}" ] || [ -z "${REPOSILITE_TOKEN}" ]; then + echo "Missing REPOSILITE_USER / REPOSILITE_TOKEN secrets." + exit 1 + fi + ./gradlew publish -x test --no-daemon + env: + REPOSILITE_USER: ${{ secrets.REPOSILITE_USER }} + REPOSILITE_TOKEN: ${{ secrets.REPOSILITE_TOKEN }} + + - name: Create GitHub release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ steps.meta.outputs.tag }} + name: ${{ steps.meta.outputs.tag }} + generate_release_notes: true + files: | + build/libs/signgui-*.jar diff --git a/.gitignore b/.gitignore index fd7eb322..b46ec5be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,41 @@ -.idea/ -*.iml -target/ -test/ -dependency-reduced-pom.xml -.mvn/ -.flattened-pom.xml -.paper-nms/ +# Gradle +.gradle +*.bat +*.log +**/build/ +!src/**/build/ +bin/* +*.class + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# MkDocs GitLab Pages output +/public/ + +#Obfuscation +/libs +/skidfuscator/mappings +*.txt +!docs-requirements.txt +/skidfuscator/libs +/mappings +/wrapper +/.paper-nms +*.salive diff --git a/1_10_R1/build.gradle.kts b/1_10_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_10_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_10_R1/pom.xml b/1_10_R1/pom.xml deleted file mode 100644 index fc61fcd3..00000000 --- a/1_10_R1/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_10_R1 - - - true - - - - - org.spigotmc - spigot - 1.10.2-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_10_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_10_R1.java b/1_10_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_10_R1.java index 04dd501d..85ffac03 100644 --- a/1_10_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_10_R1.java +++ b/1_10_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_10_R1.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @SuppressWarnings("deprecation") @@ -92,7 +91,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_11_R1/build.gradle.kts b/1_11_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_11_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_11_R1/pom.xml b/1_11_R1/pom.xml deleted file mode 100644 index f3460dc8..00000000 --- a/1_11_R1/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_11_R1 - - - true - - - - - org.spigotmc - spigot - 1.11-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_11_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_11_R1.java b/1_11_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_11_R1.java index 13c5c7a8..2750150b 100644 --- a/1_11_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_11_R1.java +++ b/1_11_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_11_R1.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @SuppressWarnings("deprecation") @@ -92,7 +91,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_12_R1/build.gradle.kts b/1_12_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_12_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_12_R1/pom.xml b/1_12_R1/pom.xml deleted file mode 100644 index 42df0429..00000000 --- a/1_12_R1/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_12_R1 - - - true - - - - - org.spigotmc - spigot - 1.12-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_12_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_12_R1.java b/1_12_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_12_R1.java index c9d6b19c..b379981d 100644 --- a/1_12_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_12_R1.java +++ b/1_12_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_12_R1.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @SuppressWarnings("deprecation") @@ -92,7 +91,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_13_R1/build.gradle.kts b/1_13_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_13_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_13_R1/pom.xml b/1_13_R1/pom.xml deleted file mode 100644 index b09a6ca3..00000000 --- a/1_13_R1/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_13_R1 - - - true - - - - - org.spigotmc - spigot - 1.13-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_13_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_13_R1.java b/1_13_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_13_R1.java index 1a74609a..52b44e9a 100644 --- a/1_13_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_13_R1.java +++ b/1_13_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_13_R1.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_13_R1 implements VersionWrapper { @@ -91,7 +90,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_13_R2/build.gradle.kts b/1_13_R2/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_13_R2/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_13_R2/pom.xml b/1_13_R2/pom.xml deleted file mode 100644 index 46c70a26..00000000 --- a/1_13_R2/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_13_R2 - - - true - - - - - org.spigotmc - spigot - 1.13.1-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_13_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_13_R2.java b/1_13_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_13_R2.java index f55f0284..765131f7 100644 --- a/1_13_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_13_R2.java +++ b/1_13_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_13_R2.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_13_R2 implements VersionWrapper { @@ -91,7 +90,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_14_R1/build.gradle.kts b/1_14_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_14_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_14_R1/pom.xml b/1_14_R1/pom.xml deleted file mode 100644 index f13a7647..00000000 --- a/1_14_R1/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_14_R1 - - - true - - - - - org.spigotmc - spigot - 1.14-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_14_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_14_R1.java b/1_14_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_14_R1.java index 64bf7761..72bf274d 100644 --- a/1_14_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_14_R1.java +++ b/1_14_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_14_R1.java @@ -16,7 +16,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.regex.Pattern; @@ -107,7 +106,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_15_R1/build.gradle.kts b/1_15_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_15_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_15_R1/pom.xml b/1_15_R1/pom.xml deleted file mode 100644 index 9220ad34..00000000 --- a/1_15_R1/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_15_R1 - - - true - - - - - org.spigotmc - spigot - 1.15-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_15_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_15_R1.java b/1_15_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_15_R1.java index ed311abe..fb090355 100644 --- a/1_15_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_15_R1.java +++ b/1_15_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_15_R1.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_15_R1 implements VersionWrapper { @@ -97,7 +96,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_16_R1/build.gradle.kts b/1_16_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_16_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_16_R1/pom.xml b/1_16_R1/pom.xml deleted file mode 100644 index 1fa63f6e..00000000 --- a/1_16_R1/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_16_R1 - - - true - - - - - org.spigotmc - spigot - 1.16.1-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_16_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R1.java b/1_16_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R1.java index 25f76ff2..fc23258a 100644 --- a/1_16_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R1.java +++ b/1_16_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R1.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_16_R1 implements VersionWrapper { @@ -97,7 +96,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_16_R2/build.gradle.kts b/1_16_R2/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_16_R2/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_16_R2/pom.xml b/1_16_R2/pom.xml deleted file mode 100644 index 12bc1834..00000000 --- a/1_16_R2/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_16_R2 - - - true - - - - - org.spigotmc - spigot - 1.16.2-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_16_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R2.java b/1_16_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R2.java index ec32caa1..ba7f3534 100644 --- a/1_16_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R2.java +++ b/1_16_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R2.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_16_R2 implements VersionWrapper { @@ -97,7 +96,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_16_R3/build.gradle.kts b/1_16_R3/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_16_R3/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_16_R3/pom.xml b/1_16_R3/pom.xml deleted file mode 100644 index 10d46d47..00000000 --- a/1_16_R3/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_16_R3 - - - true - - - - - org.spigotmc - spigot - 1.16.4-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_16_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R3.java b/1_16_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R3.java index 7db5d548..e4ecc2b1 100644 --- a/1_16_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R3.java +++ b/1_16_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_16_R3.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_16_R3 implements VersionWrapper { @@ -97,7 +96,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_17_R1/build.gradle.kts b/1_17_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_17_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_17_R1/pom.xml b/1_17_R1/pom.xml deleted file mode 100644 index 665a2458..00000000 --- a/1_17_R1/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_17_R1 - - - true - - - - - org.spigotmc - spigot - 1.17-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 16 - 16 - - - - - diff --git a/1_17_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_17_R1.java b/1_17_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_17_R1.java index dbac24e6..26835f8a 100644 --- a/1_17_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_17_R1.java +++ b/1_17_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_17_R1.java @@ -22,7 +22,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_17_R1 implements VersionWrapper { @@ -103,7 +102,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_18_R1/build.gradle.kts b/1_18_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_18_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_18_R1/pom.xml b/1_18_R1/pom.xml deleted file mode 100644 index 114afbe1..00000000 --- a/1_18_R1/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_18_R1 - - - true - - - - - org.spigotmc - spigot - 1.18-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 17 - 17 - - - - - diff --git a/1_18_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_18_R1.java b/1_18_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_18_R1.java index 16eba23c..ce840f8c 100644 --- a/1_18_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_18_R1.java +++ b/1_18_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_18_R1.java @@ -22,7 +22,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_18_R1 implements VersionWrapper { @@ -103,7 +102,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_18_R2/build.gradle.kts b/1_18_R2/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_18_R2/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_18_R2/pom.xml b/1_18_R2/pom.xml deleted file mode 100644 index b307410f..00000000 --- a/1_18_R2/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_18_R2 - - - true - - - - - org.spigotmc - spigot - 1.18.2-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 17 - 17 - - - - - diff --git a/1_18_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_18_R2.java b/1_18_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_18_R2.java index 6ff8203d..866be38a 100644 --- a/1_18_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_18_R2.java +++ b/1_18_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_18_R2.java @@ -22,7 +22,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_18_R2 implements VersionWrapper { @@ -103,7 +102,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_19_R1/build.gradle.kts b/1_19_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_19_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_19_R1/pom.xml b/1_19_R1/pom.xml deleted file mode 100644 index 09fdbfe9..00000000 --- a/1_19_R1/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_19_R1 - - - true - - - - - org.spigotmc - spigot - 1.19-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 17 - 17 - - - - - diff --git a/1_19_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R1.java b/1_19_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R1.java index 34558e75..db631dcd 100644 --- a/1_19_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R1.java +++ b/1_19_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R1.java @@ -22,7 +22,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_19_R1 implements VersionWrapper { @@ -103,7 +102,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_19_R2/build.gradle.kts b/1_19_R2/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_19_R2/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_19_R2/pom.xml b/1_19_R2/pom.xml deleted file mode 100644 index 6af12bc3..00000000 --- a/1_19_R2/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_19_R2 - - - true - - - - - org.spigotmc - spigot - 1.19.3-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 17 - 17 - - - - - diff --git a/1_19_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R2.java b/1_19_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R2.java index 208febad..159f372a 100644 --- a/1_19_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R2.java +++ b/1_19_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R2.java @@ -22,7 +22,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_19_R2 implements VersionWrapper { @@ -105,7 +104,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_19_R3/build.gradle.kts b/1_19_R3/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_19_R3/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_19_R3/pom.xml b/1_19_R3/pom.xml deleted file mode 100644 index dde640b6..00000000 --- a/1_19_R3/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_19_R3 - - - true - - - - - org.spigotmc - spigot - 1.19.4-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 17 - 17 - - - - - diff --git a/1_19_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R3.java b/1_19_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R3.java index 09e2b041..681c1581 100644 --- a/1_19_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R3.java +++ b/1_19_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_19_R3.java @@ -24,7 +24,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_19_R3 implements VersionWrapper { @@ -132,7 +131,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_20_R1/build.gradle.kts b/1_20_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_20_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_20_R1/pom.xml b/1_20_R1/pom.xml deleted file mode 100644 index 5b5a8233..00000000 --- a/1_20_R1/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_20_R1 - - - true - - - - - org.spigotmc - spigot - 1.20-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 17 - 17 - - - - - diff --git a/1_20_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R1.java b/1_20_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R1.java index 5c23fab2..7fcd76e2 100644 --- a/1_20_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R1.java +++ b/1_20_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R1.java @@ -25,7 +25,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_20_R1 implements VersionWrapper { @@ -135,7 +134,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_20_R2/build.gradle.kts b/1_20_R2/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_20_R2/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_20_R2/pom.xml b/1_20_R2/pom.xml deleted file mode 100644 index 050a37fd..00000000 --- a/1_20_R2/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_20_R2 - - - true - - - - - org.spigotmc - spigot - 1.20.2-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 17 - 17 - - - - - diff --git a/1_20_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R2.java b/1_20_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R2.java index 56ee173d..e1be23e6 100644 --- a/1_20_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R2.java +++ b/1_20_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R2.java @@ -26,7 +26,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_20_R2 implements VersionWrapper { @@ -136,7 +135,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_20_R3/build.gradle.kts b/1_20_R3/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_20_R3/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_20_R3/pom.xml b/1_20_R3/pom.xml deleted file mode 100644 index 83209f51..00000000 --- a/1_20_R3/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_20_R3 - - - true - - - - - org.spigotmc - spigot - 1.20.3-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 17 - 17 - - - - - diff --git a/1_20_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R3.java b/1_20_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R3.java index 25678f91..1427bd36 100644 --- a/1_20_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R3.java +++ b/1_20_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R3.java @@ -26,7 +26,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_20_R3 implements VersionWrapper { @@ -136,7 +135,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_20_R4/build.gradle.kts b/1_20_R4/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_20_R4/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_20_R4/pom.xml b/1_20_R4/pom.xml deleted file mode 100644 index ea7ba53e..00000000 --- a/1_20_R4/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_20_R4 - - - true - - - - - org.spigotmc - spigot - 1.20.5-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - - diff --git a/1_20_R4/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R4.java b/1_20_R4/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R4.java index aa2006e1..25001bcd 100644 --- a/1_20_R4/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R4.java +++ b/1_20_R4/src/main/java/de/rapha149/signgui/version/Wrapper1_20_R4.java @@ -27,7 +27,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_20_R4 implements VersionWrapper { @@ -139,7 +138,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_21_R1/build.gradle.kts b/1_21_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_21_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_21_R1/pom.xml b/1_21_R1/pom.xml deleted file mode 100644 index a29ec802..00000000 --- a/1_21_R1/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_21_R1 - - - true - - - - - org.spigotmc - spigot - 1.21.1-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - - diff --git a/1_21_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R1.java b/1_21_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R1.java index 6a9e9f3d..6aa13edf 100644 --- a/1_21_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R1.java +++ b/1_21_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R1.java @@ -28,7 +28,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_21_R1 implements VersionWrapper { @@ -140,7 +139,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_21_R2/build.gradle.kts b/1_21_R2/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_21_R2/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_21_R2/pom.xml b/1_21_R2/pom.xml deleted file mode 100644 index bd44edb1..00000000 --- a/1_21_R2/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_21_R2 - - - true - - - - - org.spigotmc - spigot - 1.21.3-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - - diff --git a/1_21_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R2.java b/1_21_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R2.java index ee116f50..2242e965 100644 --- a/1_21_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R2.java +++ b/1_21_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R2.java @@ -28,7 +28,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_21_R2 implements VersionWrapper { @@ -140,7 +139,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_21_R3/build.gradle.kts b/1_21_R3/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_21_R3/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_21_R3/pom.xml b/1_21_R3/pom.xml deleted file mode 100644 index f8acfdff..00000000 --- a/1_21_R3/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_21_R3 - - - true - - - - - org.spigotmc - spigot - 1.21.4-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - - diff --git a/1_21_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R3.java b/1_21_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R3.java index 7753cca1..eeb7ce23 100644 --- a/1_21_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R3.java +++ b/1_21_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R3.java @@ -28,7 +28,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_21_R3 implements VersionWrapper { @@ -140,7 +139,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_21_R4/build.gradle.kts b/1_21_R4/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_21_R4/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_21_R4/pom.xml b/1_21_R4/pom.xml deleted file mode 100644 index b07307a5..00000000 --- a/1_21_R4/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_21_R4 - - - true - - - - - org.spigotmc - spigot - 1.21.5-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - - diff --git a/1_21_R4/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R4.java b/1_21_R4/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R4.java index 41fd5e7c..fa776c61 100644 --- a/1_21_R4/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R4.java +++ b/1_21_R4/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R4.java @@ -28,7 +28,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_21_R4 implements VersionWrapper { @@ -140,7 +139,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_21_R5/build.gradle.kts b/1_21_R5/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_21_R5/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_21_R5/pom.xml b/1_21_R5/pom.xml deleted file mode 100644 index 90df4375..00000000 --- a/1_21_R5/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_21_R5 - - - true - - - - - org.spigotmc - spigot - 1.21.6-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - - diff --git a/1_21_R5/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R5.java b/1_21_R5/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R5.java index fe2145d9..86fdbaeb 100644 --- a/1_21_R5/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R5.java +++ b/1_21_R5/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R5.java @@ -28,7 +28,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class Wrapper1_21_R5 implements VersionWrapper { @@ -140,7 +139,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_21_R6/build.gradle.kts b/1_21_R6/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_21_R6/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_21_R6/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R6.java b/1_21_R6/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R6.java new file mode 100644 index 00000000..8278add5 --- /dev/null +++ b/1_21_R6/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R6.java @@ -0,0 +1,170 @@ +package de.rapha149.signgui.version; + +import de.rapha149.signgui.SignEditor; +import de.rapha149.signgui.SignGUIChannelHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import net.minecraft.core.BlockPosition; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.chat.IChatBaseComponent; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.PacketPlayInUpdateSign; +import net.minecraft.network.protocol.game.PacketPlayOutOpenSignEditor; +import net.minecraft.server.level.EntityPlayer; +import net.minecraft.server.network.PlayerConnection; +import net.minecraft.server.network.ServerCommonPacketListenerImpl; +import net.minecraft.world.item.EnumColor; +import net.minecraft.world.level.World; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.SignText; +import net.minecraft.world.level.block.entity.TileEntitySign; +import org.bukkit.DyeColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_21_R6.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.function.BiConsumer; + +public class Wrapper1_21_R6 implements VersionWrapper { + + private final Field NETWORK_MANAGER_FIELD; + + { + Field networkManagerField = null; + for (Field field : ServerCommonPacketListenerImpl.class.getDeclaredFields()) { + if (field.getType() == NetworkManager.class) { + field.setAccessible(true); + networkManagerField = field; + break; + } + } + + NETWORK_MANAGER_FIELD = networkManagerField; + } + + @Override + public Material getDefaultType() { + return Material.OAK_WALL_SIGN; + } + + @Override + public List getSignTypes() { + return Arrays.asList( + Material.OAK_SIGN, Material.BIRCH_SIGN, Material.SPRUCE_SIGN, Material.JUNGLE_SIGN, + Material.ACACIA_SIGN, Material.DARK_OAK_SIGN, Material.CRIMSON_SIGN, Material.WARPED_SIGN, + Material.CHERRY_SIGN, Material.MANGROVE_SIGN, Material.BAMBOO_SIGN, Material.PALE_OAK_SIGN, + Material.OAK_WALL_SIGN, Material.BIRCH_WALL_SIGN, Material.SPRUCE_WALL_SIGN, Material.JUNGLE_WALL_SIGN, + Material.ACACIA_WALL_SIGN, Material.DARK_OAK_WALL_SIGN, Material.CRIMSON_WALL_SIGN, Material.WARPED_WALL_SIGN, + Material.CHERRY_WALL_SIGN, Material.MANGROVE_WALL_SIGN, Material.BAMBOO_WALL_SIGN, Material.PALE_OAK_WALL_SIGN + ); + } + + @Override + public void openSignEditor(Player player, String[] lines, Object[] adventureLines, Material type, DyeColor color, boolean glow, Location signLoc, BiConsumer onFinish) throws IllegalAccessException { + EntityPlayer p = ((CraftPlayer) player).getHandle(); + PlayerConnection conn = p.g; + + if (NETWORK_MANAGER_FIELD == null) + throw new IllegalStateException("Unable to find NetworkManager field in PlayerConnection class."); + if (!NETWORK_MANAGER_FIELD.canAccess(conn)) { + NETWORK_MANAGER_FIELD.setAccessible(true); + if (!NETWORK_MANAGER_FIELD.canAccess(conn)) + throw new IllegalStateException("Unable to access NetworkManager field in PlayerConnection class."); + } + + Location loc = signLoc != null ? signLoc : getDefaultLocation(player); + BlockPosition pos = new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + + TileEntitySign sign = new TileEntitySign(pos, Blocks.cP.m()); + SignText signText = sign.a(true) // flag = front/back of sign + .a(EnumColor.valueOf(color.toString())) + .a(glow); + for (int i = 0; i < lines.length; i++) + signText = signText.a(i, IChatBaseComponent.a(lines[i])); + sign.a(signText, true); + + boolean schedule = false; + NetworkManager manager = (NetworkManager) NETWORK_MANAGER_FIELD.get(conn); + ChannelPipeline pipeline = manager.n.pipeline(); + if (pipeline.names().contains("SignGUI")) { + ChannelHandler handler = pipeline.get("SignGUI"); + if (handler instanceof SignGUIChannelHandler signGUIHandler) { + signGUIHandler.close(); + schedule = signGUIHandler.getBlockPosition().equals(pos); + } + + if (pipeline.names().contains("SignGUI")) + pipeline.remove("SignGUI"); + } + + Runnable runnable = () -> { + player.sendBlockChange(loc, type.createBlockData()); + sign.a(p.an()); + conn.b(sign.l()); + sign.a((World) null); + conn.b(new PacketPlayOutOpenSignEditor(pos, true)); // flag = front/back of sign + + SignEditor signEditor = new SignEditor(sign, loc, pos, pipeline); + pipeline.addAfter("decoder", "SignGUI", new SignGUIChannelHandler>() { + + @Override + public Object getBlockPosition() { + return pos; + } + + @Override + public void close() { + closeSignEditor(player, signEditor); + } + + @Override + protected void decode(ChannelHandlerContext chc, Packet packet, List out) { + try { + if (packet instanceof PacketPlayInUpdateSign updateSign) { + if (updateSign.b().equals(pos)) + onFinish.accept(signEditor, updateSign.f()); + } + } catch (Exception e) { + e.printStackTrace(); + } + + out.add(packet); + } + }); + }; + + if (schedule) + scheduleReopen(player, loc, runnable); + else + runnable.run(); + } + + @Override + public void displayNewLines(Player player, SignEditor signEditor, String[] lines, Object[] adventureLines) { + TileEntitySign sign = (TileEntitySign) signEditor.getSign(); + + SignText newSignText = sign.a(true); + for (int i = 0; i < lines.length; i++) + newSignText = newSignText.a(i, IChatBaseComponent.a(lines[i])); + sign.a(newSignText, true); + + EntityPlayer p = ((CraftPlayer) player).getHandle(); + PlayerConnection conn = p.g; + sign.a(p.an()); + conn.b(sign.l()); + sign.a((World) null); + conn.b(new PacketPlayOutOpenSignEditor((BlockPosition) signEditor.getBlockPosition(), true)); + } + + @Override + public void closeSignEditor(Player player, SignEditor signEditor) { + Location loc = signEditor.getLocation(); + signEditor.getPipeline().remove("SignGUI"); + player.sendBlockChange(loc, loc.getBlock().getBlockData()); + } +} diff --git a/1_21_R7/build.gradle.kts b/1_21_R7/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_21_R7/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_21_R7/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R7.java b/1_21_R7/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R7.java new file mode 100644 index 00000000..2766bd38 --- /dev/null +++ b/1_21_R7/src/main/java/de/rapha149/signgui/version/Wrapper1_21_R7.java @@ -0,0 +1,170 @@ +package de.rapha149.signgui.version; + +import de.rapha149.signgui.SignEditor; +import de.rapha149.signgui.SignGUIChannelHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import net.minecraft.core.BlockPosition; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.chat.IChatBaseComponent; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.PacketPlayInUpdateSign; +import net.minecraft.network.protocol.game.PacketPlayOutOpenSignEditor; +import net.minecraft.server.level.EntityPlayer; +import net.minecraft.server.network.PlayerConnection; +import net.minecraft.server.network.ServerCommonPacketListenerImpl; +import net.minecraft.world.item.EnumColor; +import net.minecraft.world.level.World; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.SignText; +import net.minecraft.world.level.block.entity.TileEntitySign; +import org.bukkit.DyeColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_21_R7.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.function.BiConsumer; + +public class Wrapper1_21_R7 implements VersionWrapper { + + private final Field NETWORK_MANAGER_FIELD; + + { + Field networkManagerField = null; + for (Field field : ServerCommonPacketListenerImpl.class.getDeclaredFields()) { + if (field.getType() == NetworkManager.class) { + field.setAccessible(true); + networkManagerField = field; + break; + } + } + + NETWORK_MANAGER_FIELD = networkManagerField; + } + + @Override + public Material getDefaultType() { + return Material.OAK_WALL_SIGN; + } + + @Override + public List getSignTypes() { + return Arrays.asList( + Material.OAK_SIGN, Material.BIRCH_SIGN, Material.SPRUCE_SIGN, Material.JUNGLE_SIGN, + Material.ACACIA_SIGN, Material.DARK_OAK_SIGN, Material.CRIMSON_SIGN, Material.WARPED_SIGN, + Material.CHERRY_SIGN, Material.MANGROVE_SIGN, Material.BAMBOO_SIGN, Material.PALE_OAK_SIGN, + Material.OAK_WALL_SIGN, Material.BIRCH_WALL_SIGN, Material.SPRUCE_WALL_SIGN, Material.JUNGLE_WALL_SIGN, + Material.ACACIA_WALL_SIGN, Material.DARK_OAK_WALL_SIGN, Material.CRIMSON_WALL_SIGN, Material.WARPED_WALL_SIGN, + Material.CHERRY_WALL_SIGN, Material.MANGROVE_WALL_SIGN, Material.BAMBOO_WALL_SIGN, Material.PALE_OAK_WALL_SIGN + ); + } + + @Override + public void openSignEditor(Player player, String[] lines, Object[] adventureLines, Material type, DyeColor color, boolean glow, Location signLoc, BiConsumer onFinish) throws IllegalAccessException { + EntityPlayer p = ((CraftPlayer) player).getHandle(); + PlayerConnection conn = p.g; + + if (NETWORK_MANAGER_FIELD == null) + throw new IllegalStateException("Unable to find NetworkManager field in PlayerConnection class."); + if (!NETWORK_MANAGER_FIELD.canAccess(conn)) { + NETWORK_MANAGER_FIELD.setAccessible(true); + if (!NETWORK_MANAGER_FIELD.canAccess(conn)) + throw new IllegalStateException("Unable to access NetworkManager field in PlayerConnection class."); + } + + Location loc = signLoc != null ? signLoc : getDefaultLocation(player); + BlockPosition pos = new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + + TileEntitySign sign = new TileEntitySign(pos, Blocks.cP.m()); + SignText signText = sign.a(true) // flag = front/back of sign + .a(EnumColor.valueOf(color.toString())) + .a(glow); + for (int i = 0; i < lines.length; i++) + signText = signText.a(i, IChatBaseComponent.a(lines[i])); + sign.a(signText, true); + + boolean schedule = false; + NetworkManager manager = (NetworkManager) NETWORK_MANAGER_FIELD.get(conn); + ChannelPipeline pipeline = manager.k.pipeline(); + if (pipeline.names().contains("SignGUI")) { + ChannelHandler handler = pipeline.get("SignGUI"); + if (handler instanceof SignGUIChannelHandler signGUIHandler) { + signGUIHandler.close(); + schedule = signGUIHandler.getBlockPosition().equals(pos); + } + + if (pipeline.names().contains("SignGUI")) + pipeline.remove("SignGUI"); + } + + Runnable runnable = () -> { + player.sendBlockChange(loc, type.createBlockData()); + sign.a(p.ao()); + conn.b(sign.l()); + sign.a((World) null); + conn.b(new PacketPlayOutOpenSignEditor(pos, true)); // flag = front/back of sign + + SignEditor signEditor = new SignEditor(sign, loc, pos, pipeline); + pipeline.addAfter("decoder", "SignGUI", new SignGUIChannelHandler>() { + + @Override + public Object getBlockPosition() { + return pos; + } + + @Override + public void close() { + closeSignEditor(player, signEditor); + } + + @Override + protected void decode(ChannelHandlerContext chc, Packet packet, List out) { + try { + if (packet instanceof PacketPlayInUpdateSign updateSign) { + if (updateSign.b().equals(pos)) + onFinish.accept(signEditor, updateSign.f()); + } + } catch (Exception e) { + e.printStackTrace(); + } + + out.add(packet); + } + }); + }; + + if (schedule) + scheduleReopen(player, loc, runnable); + else + runnable.run(); + } + + @Override + public void displayNewLines(Player player, SignEditor signEditor, String[] lines, Object[] adventureLines) { + TileEntitySign sign = (TileEntitySign) signEditor.getSign(); + + SignText newSignText = sign.a(true); + for (int i = 0; i < lines.length; i++) + newSignText = newSignText.a(i, IChatBaseComponent.a(lines[i])); + sign.a(newSignText, true); + + EntityPlayer p = ((CraftPlayer) player).getHandle(); + PlayerConnection conn = p.g; + sign.a(p.ao()); + conn.b(sign.l()); + sign.a((World) null); + conn.b(new PacketPlayOutOpenSignEditor((BlockPosition) signEditor.getBlockPosition(), true)); + } + + @Override + public void closeSignEditor(Player player, SignEditor signEditor) { + Location loc = signEditor.getLocation(); + signEditor.getPipeline().remove("SignGUI"); + player.sendBlockChange(loc, loc.getBlock().getBlockData()); + } +} diff --git a/1_8_R1/build.gradle.kts b/1_8_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_8_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_8_R1/pom.xml b/1_8_R1/pom.xml deleted file mode 100644 index 42d04141..00000000 --- a/1_8_R1/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_8_R1 - - - true - - - - - org.spigotmc - spigot - 1.8-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_8_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R1.java b/1_8_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R1.java index 9c00e292..db14b8f5 100644 --- a/1_8_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R1.java +++ b/1_8_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R1.java @@ -16,7 +16,6 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @SuppressWarnings("deprecation") @@ -98,7 +97,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List out }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_8_R2/build.gradle.kts b/1_8_R2/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_8_R2/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_8_R2/pom.xml b/1_8_R2/pom.xml deleted file mode 100644 index 8ca52fd6..00000000 --- a/1_8_R2/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_8_R2 - - - true - - - - - org.spigotmc - spigot - 1.8.3-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_8_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R2.java b/1_8_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R2.java index a63ce827..d8a64996 100644 --- a/1_8_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R2.java +++ b/1_8_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R2.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @SuppressWarnings("deprecation") @@ -92,7 +91,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_8_R3/build.gradle.kts b/1_8_R3/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_8_R3/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_8_R3/pom.xml b/1_8_R3/pom.xml deleted file mode 100644 index f9586a68..00000000 --- a/1_8_R3/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_8_R3 - - - true - - - - - org.spigotmc - spigot - 1.8.8-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_8_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R3.java b/1_8_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R3.java index 416e0db6..18edd951 100644 --- a/1_8_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R3.java +++ b/1_8_R3/src/main/java/de/rapha149/signgui/version/Wrapper1_8_R3.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @SuppressWarnings("deprecation") @@ -92,7 +91,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_9_R1/build.gradle.kts b/1_9_R1/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_9_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_9_R1/pom.xml b/1_9_R1/pom.xml deleted file mode 100644 index deb05a8a..00000000 --- a/1_9_R1/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_9_R1 - - - true - - - - - org.spigotmc - spigot - 1.9-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_9_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_9_R1.java b/1_9_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_9_R1.java index ff8612bb..09beb0bc 100644 --- a/1_9_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_9_R1.java +++ b/1_9_R1/src/main/java/de/rapha149/signgui/version/Wrapper1_9_R1.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @SuppressWarnings("deprecation") @@ -92,7 +91,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/1_9_R2/build.gradle.kts b/1_9_R2/build.gradle.kts new file mode 100644 index 00000000..5affcfc9 --- /dev/null +++ b/1_9_R2/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("spigot") +} \ No newline at end of file diff --git a/1_9_R2/pom.xml b/1_9_R2/pom.xml deleted file mode 100644 index ca25d2aa..00000000 --- a/1_9_R2/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - 4.0.0 - - signgui-1_9_R2 - - - true - - - - - org.spigotmc - spigot - 1.9.4-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - diff --git a/1_9_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_9_R2.java b/1_9_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_9_R2.java index 34cf67f4..456735d0 100644 --- a/1_9_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_9_R2.java +++ b/1_9_R2/src/main/java/de/rapha149/signgui/version/Wrapper1_9_R2.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @SuppressWarnings("deprecation") @@ -92,7 +91,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/Mojang1_20_R4/build.gradle.kts b/Mojang1_20_R4/build.gradle.kts new file mode 100644 index 00000000..20206291 --- /dev/null +++ b/Mojang1_20_R4/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("papermc-mojang") +} \ No newline at end of file diff --git a/Mojang1_20_R4/pom.xml b/Mojang1_20_R4/pom.xml deleted file mode 100644 index f046623b..00000000 --- a/Mojang1_20_R4/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - signgui-parent - 2.5.4 - de.rapha149.signgui - - 4.0.0 - - signgui-1_20_R4-mojang - - - true - - - - - - ca.bkaw - paper-nms - 1.20.6-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - bytecode.space - https://repo.bytecode.space/repository/maven-public/ - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - ca.bkaw - paper-nms-maven-plugin - 1.4.7 - - - - diff --git a/Mojang1_20_R4/src/main/java/de/rapha149/signgui/version/MojangWrapper1_20_R4.java b/Mojang1_20_R4/src/main/java/de/rapha149/signgui/version/MojangWrapper1_20_R4.java index 34e345c7..4f06bec8 100644 --- a/Mojang1_20_R4/src/main/java/de/rapha149/signgui/version/MojangWrapper1_20_R4.java +++ b/Mojang1_20_R4/src/main/java/de/rapha149/signgui/version/MojangWrapper1_20_R4.java @@ -24,7 +24,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class MojangWrapper1_20_R4 implements VersionWrapper { @@ -135,7 +134,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/Mojang1_21_R1/build.gradle.kts b/Mojang1_21_R1/build.gradle.kts new file mode 100644 index 00000000..20206291 --- /dev/null +++ b/Mojang1_21_R1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("papermc-mojang") +} \ No newline at end of file diff --git a/Mojang1_21_R1/pom.xml b/Mojang1_21_R1/pom.xml deleted file mode 100644 index c52f7d20..00000000 --- a/Mojang1_21_R1/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - signgui-parent - 2.5.4 - de.rapha149.signgui - - 4.0.0 - - signgui-1_21_R1-mojang - - - true - - - - - - ca.bkaw - paper-nms - 1.21.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - bytecode.space - https://repo.bytecode.space/repository/maven-public/ - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - ca.bkaw - paper-nms-maven-plugin - 1.4.7 - - - - diff --git a/Mojang1_21_R1/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R1.java b/Mojang1_21_R1/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R1.java index b14b496f..37953062 100644 --- a/Mojang1_21_R1/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R1.java +++ b/Mojang1_21_R1/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R1.java @@ -25,7 +25,6 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class MojangWrapper1_21_R1 implements VersionWrapper { @@ -136,7 +135,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/Mojang1_21_R2/build.gradle.kts b/Mojang1_21_R2/build.gradle.kts new file mode 100644 index 00000000..20206291 --- /dev/null +++ b/Mojang1_21_R2/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("papermc-mojang") +} \ No newline at end of file diff --git a/Mojang1_21_R2/pom.xml b/Mojang1_21_R2/pom.xml deleted file mode 100644 index 4668ddaf..00000000 --- a/Mojang1_21_R2/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - signgui-parent - 2.5.4 - de.rapha149.signgui - - 4.0.0 - - signgui-1_21_R2-mojang - - - true - - - - - - ca.bkaw - paper-nms - 1.21.3-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - bytecode.space - https://repo.bytecode.space/repository/maven-public/ - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - ca.bkaw - paper-nms-maven-plugin - 1.4.7 - - - - diff --git a/Mojang1_21_R3/build.gradle.kts b/Mojang1_21_R3/build.gradle.kts new file mode 100644 index 00000000..20206291 --- /dev/null +++ b/Mojang1_21_R3/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("papermc-mojang") +} \ No newline at end of file diff --git a/Mojang1_21_R3/pom.xml b/Mojang1_21_R3/pom.xml deleted file mode 100644 index 3586b6d6..00000000 --- a/Mojang1_21_R3/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - signgui-parent - 2.5.4 - de.rapha149.signgui - - 4.0.0 - - signgui-1_21_R3-mojang - - - true - - - - - - ca.bkaw - paper-nms - 1.21.4-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - bytecode.space - https://repo.bytecode.space/repository/maven-public/ - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - ca.bkaw - paper-nms-maven-plugin - 1.4.7 - - - - diff --git a/Mojang1_21_R4/build.gradle.kts b/Mojang1_21_R4/build.gradle.kts new file mode 100644 index 00000000..20206291 --- /dev/null +++ b/Mojang1_21_R4/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("papermc-mojang") +} \ No newline at end of file diff --git a/Mojang1_21_R4/pom.xml b/Mojang1_21_R4/pom.xml deleted file mode 100644 index c6d3509e..00000000 --- a/Mojang1_21_R4/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - signgui-parent - 2.5.4 - de.rapha149.signgui - - 4.0.0 - - signgui-1_21_R4-mojang - - - true - - - - - - ca.bkaw - paper-nms - 1.21.5-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - bytecode.space - https://repo.bytecode.space/repository/maven-public/ - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - ca.bkaw - paper-nms-maven-plugin - 1.4.7 - - - - diff --git a/Mojang1_21_R4/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R4.java b/Mojang1_21_R4/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R4.java deleted file mode 100644 index 374e76f8..00000000 --- a/Mojang1_21_R4/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R4.java +++ /dev/null @@ -1,168 +0,0 @@ -package de.rapha149.signgui.version; - -import de.rapha149.signgui.SignEditor; -import de.rapha149.signgui.SignGUIChannelHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPipeline; -import io.papermc.paper.adventure.AdventureComponent; -import net.minecraft.core.BlockPos; -import net.minecraft.network.Connection; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket; -import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.SignBlockEntity; -import net.minecraft.world.level.block.entity.SignText; -import org.bukkit.DyeColor; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.entity.Player; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.function.BiConsumer; - -public class MojangWrapper1_21_R4 implements VersionWrapper { - - @Override - public Material getDefaultType() { - return Material.OAK_WALL_SIGN; - } - - @Override - public List getSignTypes() { - return Arrays.asList( - Material.OAK_SIGN, Material.BIRCH_SIGN, Material.SPRUCE_SIGN, Material.JUNGLE_SIGN, - Material.ACACIA_SIGN, Material.DARK_OAK_SIGN, Material.CRIMSON_SIGN, Material.WARPED_SIGN, - Material.CHERRY_SIGN, Material.MANGROVE_SIGN, Material.BAMBOO_SIGN, Material.PALE_OAK_SIGN, - Material.OAK_WALL_SIGN, Material.BIRCH_WALL_SIGN, Material.SPRUCE_WALL_SIGN, Material.JUNGLE_WALL_SIGN, - Material.ACACIA_WALL_SIGN, Material.DARK_OAK_WALL_SIGN, Material.CRIMSON_WALL_SIGN, Material.WARPED_WALL_SIGN, - Material.CHERRY_WALL_SIGN, Material.MANGROVE_WALL_SIGN, Material.BAMBOO_WALL_SIGN, Material.PALE_OAK_WALL_SIGN - ); - } - - private static Component[] createLines(String[] textLines, Object[] adventureLines) { - Component[] lines = new Component[4]; - if (adventureLines != null) { - for (int i = 0; i < adventureLines.length; i++) { - Object line = adventureLines[i]; - if (line instanceof net.kyori.adventure.text.Component component) { - lines[i] = new AdventureComponent(component); - } else if (line == null) { - lines[i] = Component.empty(); - } else { - throw new IllegalArgumentException("line at index " + i + " is not net.kyori.adventure.text.Component"); - } - } - } else { - for (int i = 0; i < textLines.length; i++) - lines[i] = Component.nullToEmpty(textLines[i]); - } - return lines; - } - - @Override - public void openSignEditor(Player player, String[] textLines, Object[] adventureLines, Material type, DyeColor color, boolean glow, Location signLoc, BiConsumer onFinish) { - ServerPlayer p = ((CraftPlayer) player).getHandle(); - ServerGamePacketListenerImpl conn = p.connection; - - Location loc = signLoc != null ? signLoc : getDefaultLocation(player); - BlockPos pos = new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); - - SignBlockEntity sign = new SignBlockEntity(pos, Blocks.OAK_SIGN.defaultBlockState()); - SignText signText = sign.getText(true) // flag = front/back of sign - .setColor(net.minecraft.world.item.DyeColor.valueOf(color.toString())) - .setHasGlowingText(glow); - - Component[] lines = createLines(textLines, adventureLines); - for (int i = 0; i < lines.length; i++) - signText = signText.setMessage(i, lines[i]); - sign.setText(signText, true); - - boolean schedule = false; - Connection manager = conn.connection; - ChannelPipeline pipeline = manager.channel.pipeline(); - if (pipeline.names().contains("SignGUI")) { - ChannelHandler handler = pipeline.get("SignGUI"); - if (handler instanceof SignGUIChannelHandler signGUIHandler) { - signGUIHandler.close(); - schedule = signGUIHandler.getBlockPosition().equals(pos); - } - - if (pipeline.names().contains("SignGUI")) - pipeline.remove("SignGUI"); - } - - Runnable runnable = () -> { - player.sendBlockChange(loc, type.createBlockData()); - sign.setLevel(p.level()); - conn.send(sign.getUpdatePacket()); - sign.setLevel(null); - conn.send(new ClientboundOpenSignEditorPacket(pos, true)); // flag = front/back of sign - - SignEditor signEditor = new SignEditor(sign, loc, pos, pipeline); - pipeline.addAfter("decoder", "SignGUI", new SignGUIChannelHandler>() { - - @Override - public Object getBlockPosition() { - return pos; - } - - @Override - public void close() { - closeSignEditor(player, signEditor); - } - - @Override - protected void decode(ChannelHandlerContext chc, Packet packet, List out) { - try { - if (packet instanceof ServerboundSignUpdatePacket updateSign) { - if (updateSign.getPos().equals(pos)) - onFinish.accept(signEditor, updateSign.getLines()); - } - } catch (Exception e) { - e.printStackTrace(); - } - - out.add(packet); - } - }); - }; - - if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); - else - runnable.run(); - } - - @Override - public void displayNewLines(Player player, SignEditor signEditor, String[] textLines, Object[] adventureLines) { - SignBlockEntity sign = (SignBlockEntity)signEditor.getSign(); - - SignText newSignText = sign.getText(true); - Component[] lines = createLines(textLines, adventureLines); - for(int i = 0; i < textLines.length; ++i) - newSignText = newSignText.setMessage(i, lines[i]); - sign.setText(newSignText, true); - - ServerPlayer p = ((CraftPlayer)player).getHandle(); - ServerGamePacketListenerImpl conn = p.connection; - sign.setLevel(p.level()); - conn.send(sign.getUpdatePacket()); - sign.setLevel(null); - conn.send(new ClientboundOpenSignEditorPacket((BlockPos)signEditor.getBlockPosition(), true)); - } - - @Override - public void closeSignEditor(Player player, SignEditor signEditor) { - Location loc = signEditor.getLocation(); - signEditor.getPipeline().remove("SignGUI"); - player.sendBlockChange(loc, loc.getBlock().getBlockData()); - } -} diff --git a/Mojang1_21_R5/build.gradle.kts b/Mojang1_21_R5/build.gradle.kts new file mode 100644 index 00000000..20206291 --- /dev/null +++ b/Mojang1_21_R5/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("papermc-mojang") +} \ No newline at end of file diff --git a/Mojang1_21_R5/pom.xml b/Mojang1_21_R5/pom.xml deleted file mode 100644 index d201d020..00000000 --- a/Mojang1_21_R5/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - signgui-parent - 2.5.4 - de.rapha149.signgui - - 4.0.0 - - signgui-1_21_R5-mojang - - - true - - - - - - ca.bkaw - paper-nms - 1.21.6-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - provided - - - - - - bytecode.space - https://repo.bytecode.space/repository/maven-public/ - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 21 - 21 - - - - ca.bkaw - paper-nms-maven-plugin - 1.4.7 - - - - diff --git a/Mojang1_21_R5/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R5.java b/Mojang1_21_R5/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R5.java deleted file mode 100644 index 1977dff6..00000000 --- a/Mojang1_21_R5/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R5.java +++ /dev/null @@ -1,168 +0,0 @@ -package de.rapha149.signgui.version; - -import de.rapha149.signgui.SignEditor; -import de.rapha149.signgui.SignGUIChannelHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPipeline; -import io.papermc.paper.adventure.AdventureComponent; -import net.minecraft.core.BlockPos; -import net.minecraft.network.Connection; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket; -import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.SignBlockEntity; -import net.minecraft.world.level.block.entity.SignText; -import org.bukkit.DyeColor; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.entity.Player; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.function.BiConsumer; - -public class MojangWrapper1_21_R5 implements VersionWrapper { - - @Override - public Material getDefaultType() { - return Material.OAK_WALL_SIGN; - } - - @Override - public List getSignTypes() { - return Arrays.asList( - Material.OAK_SIGN, Material.BIRCH_SIGN, Material.SPRUCE_SIGN, Material.JUNGLE_SIGN, - Material.ACACIA_SIGN, Material.DARK_OAK_SIGN, Material.CRIMSON_SIGN, Material.WARPED_SIGN, - Material.CHERRY_SIGN, Material.MANGROVE_SIGN, Material.BAMBOO_SIGN, Material.PALE_OAK_SIGN, - Material.OAK_WALL_SIGN, Material.BIRCH_WALL_SIGN, Material.SPRUCE_WALL_SIGN, Material.JUNGLE_WALL_SIGN, - Material.ACACIA_WALL_SIGN, Material.DARK_OAK_WALL_SIGN, Material.CRIMSON_WALL_SIGN, Material.WARPED_WALL_SIGN, - Material.CHERRY_WALL_SIGN, Material.MANGROVE_WALL_SIGN, Material.BAMBOO_WALL_SIGN, Material.PALE_OAK_WALL_SIGN - ); - } - - private static Component[] createLines(String[] textLines, Object[] adventureLines) { - Component[] lines = new Component[4]; - if (adventureLines != null) { - for (int i = 0; i < adventureLines.length; i++) { - Object line = adventureLines[i]; - if (line instanceof net.kyori.adventure.text.Component component) { - lines[i] = new AdventureComponent(component); - } else if (line == null) { - lines[i] = Component.empty(); - } else { - throw new IllegalArgumentException("line at index " + i + " is not net.kyori.adventure.text.Component"); - } - } - } else { - for (int i = 0; i < textLines.length; i++) - lines[i] = Component.nullToEmpty(textLines[i]); - } - return lines; - } - - @Override - public void openSignEditor(Player player, String[] textLines, Object[] adventureLines, Material type, DyeColor color, boolean glow, Location signLoc, BiConsumer onFinish) { - ServerPlayer p = ((CraftPlayer) player).getHandle(); - ServerGamePacketListenerImpl conn = p.connection; - - Location loc = signLoc != null ? signLoc : getDefaultLocation(player); - BlockPos pos = new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); - - SignBlockEntity sign = new SignBlockEntity(pos, Blocks.OAK_SIGN.defaultBlockState()); - SignText signText = sign.getText(true) // flag = front/back of sign - .setColor(net.minecraft.world.item.DyeColor.valueOf(color.toString())) - .setHasGlowingText(glow); - - Component[] lines = createLines(textLines, adventureLines); - for (int i = 0; i < lines.length; i++) - signText = signText.setMessage(i, lines[i]); - sign.setText(signText, true); - - boolean schedule = false; - Connection manager = conn.connection; - ChannelPipeline pipeline = manager.channel.pipeline(); - if (pipeline.names().contains("SignGUI")) { - ChannelHandler handler = pipeline.get("SignGUI"); - if (handler instanceof SignGUIChannelHandler signGUIHandler) { - signGUIHandler.close(); - schedule = signGUIHandler.getBlockPosition().equals(pos); - } - - if (pipeline.names().contains("SignGUI")) - pipeline.remove("SignGUI"); - } - - Runnable runnable = () -> { - player.sendBlockChange(loc, type.createBlockData()); - sign.setLevel(p.level()); - conn.send(sign.getUpdatePacket()); - sign.setLevel(null); - conn.send(new ClientboundOpenSignEditorPacket(pos, true)); // flag = front/back of sign - - SignEditor signEditor = new SignEditor(sign, loc, pos, pipeline); - pipeline.addAfter("decoder", "SignGUI", new SignGUIChannelHandler>() { - - @Override - public Object getBlockPosition() { - return pos; - } - - @Override - public void close() { - closeSignEditor(player, signEditor); - } - - @Override - protected void decode(ChannelHandlerContext chc, Packet packet, List out) { - try { - if (packet instanceof ServerboundSignUpdatePacket updateSign) { - if (updateSign.getPos().equals(pos)) - onFinish.accept(signEditor, updateSign.getLines()); - } - } catch (Exception e) { - e.printStackTrace(); - } - - out.add(packet); - } - }); - }; - - if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); - else - runnable.run(); - } - - @Override - public void displayNewLines(Player player, SignEditor signEditor, String[] textLines, Object[] adventureLines) { - SignBlockEntity sign = (SignBlockEntity)signEditor.getSign(); - - SignText newSignText = sign.getText(true); - Component[] lines = createLines(textLines, adventureLines); - for(int i = 0; i < textLines.length; ++i) - newSignText = newSignText.setMessage(i, lines[i]); - sign.setText(newSignText, true); - - ServerPlayer p = ((CraftPlayer)player).getHandle(); - ServerGamePacketListenerImpl conn = p.connection; - sign.setLevel(p.level()); - conn.send(sign.getUpdatePacket()); - sign.setLevel(null); - conn.send(new ClientboundOpenSignEditorPacket((BlockPos)signEditor.getBlockPosition(), true)); - } - - @Override - public void closeSignEditor(Player player, SignEditor signEditor) { - Location loc = signEditor.getLocation(); - signEditor.getPipeline().remove("SignGUI"); - player.sendBlockChange(loc, loc.getBlock().getBlockData()); - } -} diff --git a/Mojang1_21_R6/build.gradle.kts b/Mojang1_21_R6/build.gradle.kts new file mode 100644 index 00000000..20206291 --- /dev/null +++ b/Mojang1_21_R6/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("papermc-mojang") +} \ No newline at end of file diff --git a/Mojang1_21_R7/build.gradle.kts b/Mojang1_21_R7/build.gradle.kts new file mode 100644 index 00000000..20206291 --- /dev/null +++ b/Mojang1_21_R7/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("papermc-mojang") +} \ No newline at end of file diff --git a/Mojang26_1/build.gradle.kts b/Mojang26_1/build.gradle.kts new file mode 100644 index 00000000..20206291 --- /dev/null +++ b/Mojang26_1/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("papermc-mojang") +} \ No newline at end of file diff --git a/Mojang26_2/build.gradle.kts b/Mojang26_2/build.gradle.kts new file mode 100644 index 00000000..20206291 --- /dev/null +++ b/Mojang26_2/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("papermc-mojang") +} \ No newline at end of file diff --git a/README.md b/README.md index 1fae7a76..7374d451 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,79 @@ -# SignGUI [![Build](https://github.com/Rapha149/SignGUI/actions/workflows/build.yml/badge.svg)](https://github.com/Rapha149/SignGUI/actions/workflows/build.yml) [![Maven Central](https://img.shields.io/maven-central/v/de.rapha149.signgui/signgui?label=Maven%20Central)](https://central.sonatype.com/artifact/de.rapha149.signgui/signgui) [![Javadoc](https://javadoc.io/badge2/de.rapha149.signgui/signgui/Javadoc.svg)](https://javadoc.io/doc/de.rapha149.signgui/signgui) +# SignGUI [![Build](https://github.com/OPmasterLEO/SignGUI/actions/workflows/build.yml/badge.svg)](https://github.com/OPmasterLEO/SignGUI/actions/workflows/build.yml) An api to get input text via a sign in Minecraft. -The api supports the Minecraft versions from `1.8` to `1.21`. +The api supports the Minecraft versions from `1.8` to `26.2` (protocol-selected wrappers). Also supports adventure text and mojang-mapped Paper plugins (1.20.5+). +Distributed via [Reposilite](http://repo.mastersmp.net/). + +## Full Platform Support +- **Bukkit / Spigot / Paper** — Full support +- **Folia** — Regionized scheduling via Entity/Region/Global/Async schedulers (plugin binding required) +- **CanvasMC / Archlight** — Supported via platform detection + +SignGUI detects the server platform and uses Paper/Folia region schedulers when available, otherwise the Bukkit scheduler. + ## Integration -Maven dependency: +Add the MasterSMP repo, then depend on the fat jar: + +**Gradle Kotlin** +```kotlin +repositories { + mavenCentral() + maven { + url = uri("http://repo.mastersmp.net/releases") + isAllowInsecureProtocol = true + } +} + +dependencies { + implementation("de.rapha149.signgui:signgui:2.6.1") +} +``` + +**Maven** ```xml + + + mastersmp + http://repo.mastersmp.net/releases + + + de.rapha149.signgui signgui - 2.5.4 + 2.6.1 ``` -In order to avoid conflicts with other plugins that also use this api, relocate the package in your maven shade plugin: +**Publish (maintainers only)** +```bash +./gradlew publish # → http://repo.mastersmp.net/releases +./gradlew publishSnapshot # → http://repo.mastersmp.net/snapshots +# Requires REPOSILITE_USER + REPOSILITE_TOKEN +``` + +| Range | Mapping | +| --- | --- | +| 1.8 – 1.20.4 | Spigot-mapped NMS modules | +| 1.20.5 – 1.21.11 | Mojang-mapped Paper (shared modern era) + Spigot modules | +| 26.1 – 26.2+ | Mojang-mapped (shared 26 era; Spigot & Paper) | + +JDK **21** runs Gradle; JDK **25** is used for Minecraft 26.x modules (Foojay toolchain). + +Wrappers are selected by **protocol version** at runtime (`ProtocolProbe` → `ProtocolVersions` → `VersionMatcher`), with CraftBukkit package / Bukkit version fallbacks for older and unversioned (26.x) servers. + +In order to avoid conflicts with other plugins that also use this api, relocate the package when shading: + +**Gradle (Shadow)** +```kotlin +tasks.shadowJar { + relocate("de.rapha149.signgui", "your.plugin.package.signgui") +} +``` + +**Maven (shade plugin)** ```xml @@ -120,10 +179,14 @@ try { return Collections.emptyList(); }) + // REQUIRED for Folia (also binds advanced region scheduling) + // RECOMMENDED for Paper / CanvasMC / Archlight / Bukkit thread safety + .callHandlerSynchronously(this) // "this" = your JavaPlugin instance + // build the SignGUI .build(); - // open the sign + // open the sign (on Folia this is scheduled on the player's entity/region thread) gui.open(player); // you can also open the sign for multiple players @@ -133,10 +196,17 @@ try { } ``` -You don't have to call all methods. Only `setHandler` is mandatory. +You don't have to call all methods. Only `setHandler` is mandatory. On **Folia**, `callHandlerSynchronously(plugin)` is also mandatory. + +**Important:** `callHandlerSynchronously(plugin)` is **REQUIRED for Folia** and **RECOMMENDED for all other platforms**. It: +- hops finish handling off the Netty thread onto the player's **EntityScheduler** (Folia/Paper) or the main thread (Bukkit) +- schedules sign opens on the correct region thread +- routes delayed reopens (~4 ticks) through region schedulers instead of a raw thread pool +- makes `SignGUIAction.openInventory` / `runSync` Folia-safe + +Public helpers also available: `SignGUIScheduler.run(player, task)`, `runAt(location, task)`, `runGlobal(task)`, `runAsync(task)`. -By default, the handler is called by an asynchronous thread. You can change that behaviour by calling the method `callHandlerSynchronously` of the builder. -An explanation for the different methods can be found on the [Javadoc](https://javadoc.io/doc/de.rapha149.signgui/signgui). +By default (non-Folia, without `callHandlerSynchronously`), the finish handler runs on the Netty thread. Prefer binding your plugin for thread safety. Also: as you can see the code catches the `SignGUIVersionException` which could be thrown by `SignGUI.builder()` if the api does not support the Minecraft version of the server. If you're interested in why this exception exists, check these [release notes](https://github.com/Rapha149/SignGUI/releases/tag/v2.5.0). diff --git a/api/build.gradle.kts b/api/build.gradle.kts new file mode 100644 index 00000000..38d4286c --- /dev/null +++ b/api/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("module-java-versions") +} + +dependencies { + api(project(":wrapper")) + compileOnly("org.spigotmc:spigot:1.8-R0.1-SNAPSHOT") + compileOnly(libs.folia.api) +} diff --git a/api/pom.xml b/api/pom.xml deleted file mode 100644 index 243b55f8..00000000 --- a/api/pom.xml +++ /dev/null @@ -1,461 +0,0 @@ - - - 4.0.0 - - - signgui-parent - 2.5.4 - de.rapha149.signgui - - - signgui - - ${project.groupId}:signgui - An api to get input text via a sign in Minecraft. - https://github.com/Rapha149/SignGUI - - - - Rapha149 - rapha@rapha149.de - https://github.com/Rapha149 - - - - - - MIT License - http://www.opensource.org/licenses/mit-license.php - - - - - scm:git:git://github.com/Rapha149/SignGUI.git - scm:git:ssh://github.com:Rapha149/SignGUI.git - http://github.com/Rapha149/SignGUI/tree/main - - - - - - org.spigotmc - spigot - 1.8-R0.1-SNAPSHOT - provided - - - de.rapha149.signgui - signgui-wrapper - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_8_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_8_R2 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_8_R3 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_9_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_9_R2 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_10_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_11_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_12_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_13_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_13_R2 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_14_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_15_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_16_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_16_R2 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_16_R3 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_17_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_18_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_18_R2 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_19_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_19_R2 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_19_R3 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_20_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_20_R2 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_20_R3 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_20_R4 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_20_R4-mojang - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_21_R1 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_21_R1-mojang - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_21_R2 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_21_R2-mojang - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_21_R3 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_21_R3-mojang - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_21_R4 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_21_R4-mojang - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_21_R5 - ${project.parent.version} - compile - - - de.rapha149.signgui - signgui-1_21_R5-mojang - ${project.parent.version} - compile - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.3 - - - package - - shade - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.2.0 - - 8 - - - - attach-javadocs - - jar - - - true - - de.rapha149.signgui:signgui-wrapper - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.6.0 - - - src-dependencies - package - - unpack-dependencies - - - sources - false - ${project.build.directory}/external-sources - de.rapha149.signgui - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 3.4.0 - - - add-source - generate-sources - - add-source - - - - ${project.build.directory}/external-sources - - - - - - - org.apache.maven.plugins - maven-source-plugin - 3.3.0 - - - attach-sources - - jar - - - - - - maven-clean-plugin - 2.5 - - - auto-clean - package - - clean - - - true - - - ${project.build.directory}/external-sources - - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 3.1.0 - - - sign-artifacts - verify - - sign - - - - - --pinentry-mode - loopback - - - - - - - org.codehaus.mojo - flatten-maven-plugin - 1.6.0 - - oss - - - - - flatten - process-resources - - flatten - - - - - flatten.clean - clean - - clean - - - - - - org.sonatype.central - central-publishing-maven-plugin - 0.1.2 - true - - central - true - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - - - - - diff --git a/api/src/main/java/de/rapha149/signgui/SignGUI.java b/api/src/main/java/de/rapha149/signgui/SignGUI.java index 1f37daa0..ec0398b6 100644 --- a/api/src/main/java/de/rapha149/signgui/SignGUI.java +++ b/api/src/main/java/de/rapha149/signgui/SignGUI.java @@ -3,9 +3,11 @@ import de.rapha149.signgui.SignGUIAction.SignGUIActionInfo; import de.rapha149.signgui.exception.SignGUIException; import de.rapha149.signgui.exception.SignGUIVersionException; +import de.rapha149.signgui.util.PlatformDetector; +import de.rapha149.signgui.util.SignGUIScheduler; +import de.rapha149.signgui.util.scheduler.SchedulerFactory; import de.rapha149.signgui.version.VersionMatcher; import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; import org.bukkit.DyeColor; import org.bukkit.Location; import org.bukkit.Material; @@ -59,13 +61,27 @@ public static SignGUIBuilder builder() throws SignGUIVersionException { *

* Note: if there already is a sign gui open for the player, it will be closed and the {@link SignGUIFinishHandler} will not be called. * It is recommended to avoid opening a sign gui for a player that already has one open. + *

+ * On Folia (and when a plugin is bound), the open is scheduled on the player's entity/region thread. * * @param player The player to open the gui for. * @throws de.rapha149.signgui.exception.SignGUIException If an error occurs while opening the gui. */ public void open(Player player) throws SignGUIException { Validate.notNull(player, "The player cannot be null"); + if (PlatformDetector.isFolia() && plugin == null) { + throw new SignGUIException("Folia requires callHandlerSynchronously(plugin) before opening a SignGUI"); + } + + if (plugin != null) { + SignGUIScheduler.setPlugin(plugin); + SchedulerFactory.getScheduler().runTask(plugin, player, () -> openNow(player)); + } else { + openNow(player); + } + } + private void openNow(Player player) { try { VersionMatcher.getWrapper().openSignEditor(player, lines, adventureLines, type, color, glow, signLoc, (signEditor, resultLines) -> { Runnable runnable = () -> { @@ -107,11 +123,18 @@ public void open(Player player) throws SignGUIException { action.execute(this, signEditor, player); }; - if (callHandlerSynchronously) - Bukkit.getScheduler().runTask(plugin, runnable); - else + // Folia always hops to the entity scheduler; elsewhere only when requested. + if (callHandlerSynchronously || PlatformDetector.isFolia()) { + if (plugin == null) { + throw new SignGUIException("callHandlerSynchronously(plugin) is required for synchronous / Folia finish handling"); + } + SchedulerFactory.getScheduler().runTask(plugin, player, runnable); + } else { runnable.run(); + } }); + } catch (SignGUIException e) { + throw e; } catch (Exception e) { throw new SignGUIException("Failed to open sign gui", e); } diff --git a/api/src/main/java/de/rapha149/signgui/SignGUIAction.java b/api/src/main/java/de/rapha149/signgui/SignGUIAction.java index 16175475..27f3debd 100644 --- a/api/src/main/java/de/rapha149/signgui/SignGUIAction.java +++ b/api/src/main/java/de/rapha149/signgui/SignGUIAction.java @@ -1,7 +1,8 @@ package de.rapha149.signgui; +import de.rapha149.signgui.util.SignGUIScheduler; +import de.rapha149.signgui.util.scheduler.SchedulerFactory; import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.plugin.java.JavaPlugin; @@ -101,7 +102,7 @@ public void execute(SignGUI gui, SignEditor signEditor, Player player) { /** * Creates a new SignGUIAction that opens an inventory. - * The inventory is opened synchronously by calling the method {@link org.bukkit.scheduler.BukkitScheduler#runTask(org.bukkit.plugin.Plugin, Runnable)} + * The inventory is opened on the player's entity/region thread (Folia/Paper) or the main thread (Bukkit). * * @param plugin Your {@link org.bukkit.plugin.java.JavaPlugin} instance * @param inventory The inventory to open @@ -122,7 +123,8 @@ public SignGUIActionInfo getInfo() { @Override public void execute(SignGUI gui, SignEditor signEditor, Player player) { - Bukkit.getScheduler().runTask(plugin, () -> player.openInventory(inventory)); + SignGUIScheduler.setPlugin(plugin); + SchedulerFactory.getScheduler().runTask(plugin, player, () -> player.openInventory(inventory)); } }; } @@ -154,7 +156,8 @@ public void execute(SignGUI gui, SignEditor signEditor, Player player) { } /** - * Creates a new SignGUIAction that runs a runnable synchronously. + * Creates a new SignGUIAction that runs a runnable on the player's entity/region thread + * (Folia/Paper) or the main thread (Bukkit). * * @param plugin Your {@link org.bukkit.plugin.java.JavaPlugin} instance * @param runnable The runnable to run @@ -175,7 +178,8 @@ public SignGUIActionInfo getInfo() { @Override public void execute(SignGUI gui, SignEditor signEditor, Player player) { - Bukkit.getScheduler().runTask(plugin, runnable); + SignGUIScheduler.setPlugin(plugin); + SchedulerFactory.getScheduler().runTask(plugin, player, runnable); } }; } diff --git a/api/src/main/java/de/rapha149/signgui/SignGUIBuilder.java b/api/src/main/java/de/rapha149/signgui/SignGUIBuilder.java index 33babccc..31efcae3 100644 --- a/api/src/main/java/de/rapha149/signgui/SignGUIBuilder.java +++ b/api/src/main/java/de/rapha149/signgui/SignGUIBuilder.java @@ -1,12 +1,13 @@ package de.rapha149.signgui; import de.rapha149.signgui.version.VersionWrapper; +import de.rapha149.signgui.util.PlatformDetector; +import de.rapha149.signgui.util.SignGUIScheduler; import org.apache.commons.lang.Validate; import org.bukkit.DyeColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import java.util.Arrays; @@ -168,14 +169,37 @@ public SignGUIBuilder setHandler(SignGUIFinishHandler handler) { } /** - * If called the handler will be called synchronously by calling the method {@link org.bukkit.scheduler.BukkitScheduler#runTask(Plugin, Runnable)} + * Binds your plugin and schedules the finish handler on the correct thread. + *

+ * Required on Folia. Recommended on all platforms. + * On Folia/Paper region platforms, work runs on the player's {@code EntityScheduler}. + * On Bukkit/Spigot, work runs on the main thread. + *

+ * Also enables delayed sign reopens (same block position) via the region scheduler + * instead of a raw thread pool. * * @param plugin Your {@link org.bukkit.plugin.java.JavaPlugin} instance. * @return The {@link SignGUIBuilder} instance */ public SignGUIBuilder callHandlerSynchronously(JavaPlugin plugin) { + Validate.notNull(plugin, "The plugin cannot be null"); this.callHandlerSynchronously = true; this.plugin = plugin; + SignGUIScheduler.setPlugin(plugin); + return this; + } + + /** + * Binds your plugin for Folia/Paper region scheduling without forcing the finish + * handler onto the entity thread. Prefer {@link #callHandlerSynchronously(JavaPlugin)}. + * + * @param plugin Your {@link org.bukkit.plugin.java.JavaPlugin} instance. + * @return The {@link SignGUIBuilder} instance + */ + public SignGUIBuilder setPlugin(JavaPlugin plugin) { + Validate.notNull(plugin, "The plugin cannot be null"); + this.plugin = plugin; + SignGUIScheduler.setPlugin(plugin); return this; } @@ -186,6 +210,11 @@ public SignGUIBuilder callHandlerSynchronously(JavaPlugin plugin) { */ public SignGUI build() { Validate.notNull(handler, "handler must be set"); + if (PlatformDetector.isFolia()) { + Validate.notNull(plugin, "Folia requires callHandlerSynchronously(plugin) (or setPlugin(plugin))"); + // Finish handling must always hop off the Netty thread on Folia. + callHandlerSynchronously = true; + } return new SignGUI(lines, adventureLines, type, color, glow, loc, handler, callHandlerSynchronously, plugin); } } diff --git a/api/src/main/java/de/rapha149/signgui/util/PlatformDetector.java b/api/src/main/java/de/rapha149/signgui/util/PlatformDetector.java new file mode 100644 index 00000000..9b6b1af1 --- /dev/null +++ b/api/src/main/java/de/rapha149/signgui/util/PlatformDetector.java @@ -0,0 +1,103 @@ +package de.rapha149.signgui.util; + +import org.bukkit.Bukkit; + +/** + * Utility class for detecting the server platform. + */ +public class PlatformDetector { + + private static PlatformType detectedPlatform; + private static boolean hasFoliaClasses; + private static boolean hasRegionScheduler; + + static { + detectPlatform(); + } + + /** + * Detects the server platform. + */ + private static void detectPlatform() { + try { + Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); + hasFoliaClasses = true; + } catch (ClassNotFoundException ignored) { + hasFoliaClasses = false; + } + + try { + Class.forName("io.papermc.paper.threadedregions.scheduler.RegionScheduler"); + hasRegionScheduler = true; + } catch (ClassNotFoundException ignored) { + hasRegionScheduler = false; + } + + String serverVersion = Bukkit.getVersion(); + String serverName = Bukkit.getName(); + + if (hasFoliaClasses && hasRegionScheduler) { + detectedPlatform = PlatformType.FOLIA; + } else if (serverVersion.contains("Canvas") || serverName.contains("Canvas")) { + detectedPlatform = PlatformType.CANVAS; + } else if (serverVersion.contains("Archlight") || serverName.contains("Archlight")) { + detectedPlatform = PlatformType.ARCHLIGHT; + } else { + detectedPlatform = PlatformType.BUKKIT; + } + } + + /** + * Gets the detected platform type. + * + * @return The detected platform type + */ + public static PlatformType getPlatformType() { + return detectedPlatform; + } + + /** + * Checks if the server is running on Folia. + * + * @return true if running on Folia, false otherwise + */ + public static boolean isFolia() { + return detectedPlatform == PlatformType.FOLIA; + } + + /** + * Checks if the server is running on CanvasMC. + * + * @return true if running on CanvasMC, false otherwise + */ + public static boolean isCanvas() { + return detectedPlatform == PlatformType.CANVAS; + } + + /** + * Checks if the server is running on Archlight. + * + * @return true if running on Archlight, false otherwise + */ + public static boolean isArchlight() { + return detectedPlatform == PlatformType.ARCHLIGHT; + } + + /** + * Checks if the server supports region-based scheduling (Folia). + * + * @return true if region scheduling is supported, false otherwise + */ + public static boolean hasRegionScheduler() { + return hasRegionScheduler; + } + + /** + * Checks if the server has Folia classes available. + * + * @return true if Folia classes are available, false otherwise + */ + public static boolean hasFoliaClasses() { + return hasFoliaClasses; + } +} diff --git a/api/src/main/java/de/rapha149/signgui/util/PlatformType.java b/api/src/main/java/de/rapha149/signgui/util/PlatformType.java new file mode 100644 index 00000000..0f394f50 --- /dev/null +++ b/api/src/main/java/de/rapha149/signgui/util/PlatformType.java @@ -0,0 +1,26 @@ +package de.rapha149.signgui.util; + +/** + * Enum representing different server platforms. + */ +public enum PlatformType { + /** + * Folia - Paper's regionized multithreaded server + */ + FOLIA, + + /** + * CanvasMC - Fork of Paper + */ + CANVAS, + + /** + * Archlight - Forge+Bukkit hybrid server + */ + ARCHLIGHT, + + /** + * Standard Bukkit/Spigot/Paper server + */ + BUKKIT +} diff --git a/api/src/main/java/de/rapha149/signgui/util/SchedulerAdapter.java b/api/src/main/java/de/rapha149/signgui/util/SchedulerAdapter.java new file mode 100644 index 00000000..9c78c23c --- /dev/null +++ b/api/src/main/java/de/rapha149/signgui/util/SchedulerAdapter.java @@ -0,0 +1,81 @@ +package de.rapha149.signgui.util; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.plugin.java.JavaPlugin; + +/** + * Adapter interface for scheduling tasks across different server platforms. + */ +public interface SchedulerAdapter { + + /** + * Runs a task synchronously on the main thread or appropriate region thread. + * + * @param plugin The plugin instance + * @param task The task to run + */ + void runTask(JavaPlugin plugin, Runnable task); + + /** + * Runs a task synchronously on the main thread or appropriate region thread. + * + * @param plugin The plugin instance + * @param entity The entity to run the task for (used for Folia region scheduling) + * @param task The task to run + */ + void runTask(JavaPlugin plugin, Entity entity, Runnable task); + + /** + * Runs a task synchronously at a specific location. + * + * @param plugin The plugin instance + * @param location The location to run the task at (used for Folia region scheduling) + * @param task The task to run + */ + void runTask(JavaPlugin plugin, Location location, Runnable task); + + /** + * Runs a task asynchronously. + * + * @param plugin The plugin instance + * @param task The task to run + */ + void runTaskAsynchronously(JavaPlugin plugin, Runnable task); + + /** + * Schedules a delayed task synchronously. + * + * @param plugin The plugin instance + * @param task The task to run + * @param delayTicks The delay in ticks + */ + void runTaskLater(JavaPlugin plugin, Runnable task, long delayTicks); + + /** + * Schedules a delayed task synchronously for an entity. + * + * @param plugin The plugin instance + * @param entity The entity to run the task for (used for Folia region scheduling) + * @param task The task to run + * @param delayTicks The delay in ticks + */ + void runTaskLater(JavaPlugin plugin, Entity entity, Runnable task, long delayTicks); + + /** + * Schedules a delayed task synchronously at a location. + * + * @param plugin The plugin instance + * @param location The location to run the task at (used for Folia region scheduling) + * @param task The task to run + * @param delayTicks The delay in ticks + */ + void runTaskLater(JavaPlugin plugin, Location location, Runnable task, long delayTicks); + + /** + * Checks if the current thread is the main server thread or appropriate region thread. + * + * @return true if on the main/region thread, false otherwise + */ + boolean isOnMainThread(); +} diff --git a/api/src/main/java/de/rapha149/signgui/util/SignGUIScheduler.java b/api/src/main/java/de/rapha149/signgui/util/SignGUIScheduler.java new file mode 100644 index 00000000..0eb866ff --- /dev/null +++ b/api/src/main/java/de/rapha149/signgui/util/SignGUIScheduler.java @@ -0,0 +1,150 @@ +package de.rapha149.signgui.util; + +import de.rapha149.signgui.SignGUIBridge; +import de.rapha149.signgui.util.scheduler.SchedulerFactory; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * Advanced SignGUI scheduling facade for Folia, Paper, and Bukkit. + *

+ * Prefers Paper/Folia region schedulers ({@code EntityScheduler}, {@code RegionScheduler}, + * {@code GlobalRegionScheduler}, {@code AsyncScheduler}) and falls back to the Bukkit + * scheduler on platforms that do not expose them. + *

+ * On Folia, a plugin must be bound via {@link #setPlugin(JavaPlugin)} (usually through + * {@code SignGUIBuilder#callHandlerSynchronously(JavaPlugin)}) before opening a sign GUI. + */ +public final class SignGUIScheduler { + + private static final ScheduledExecutorService LEGACY_FALLBACK = + Executors.newSingleThreadScheduledExecutor(r -> { + Thread t = new Thread(r, "SignGUI-LegacyScheduler"); + t.setDaemon(true); + return t; + }); + + private static volatile JavaPlugin plugin; + + private SignGUIScheduler() { + } + + /** + * Binds the owning plugin used for Folia/Paper region scheduling. + * + * @param plugin the plugin instance, may be null to clear + */ + public static void setPlugin(JavaPlugin plugin) { + SignGUIScheduler.plugin = plugin; + if (plugin != null) { + // Wire NMS reopen delays through Folia/Paper entity schedulers. + SignGUIBridge.setDelayedScheduler(SignGUIScheduler::runLater); + } + } + + /** + * @return the bound plugin, or null if none was set + */ + public static JavaPlugin getPlugin() { + return plugin; + } + + /** + * Runs {@code task} on the player's owning region/entity thread (or the main thread on Bukkit). + */ + public static void run(Player player, Runnable task) { + JavaPlugin p = requirePluginForFolia(); + if (p != null && player != null) { + SchedulerFactory.getScheduler().runTask(p, player, task); + return; + } + if (p != null) { + SchedulerFactory.getScheduler().runTask(p, task); + return; + } + task.run(); + } + + /** + * Runs {@code task} on the region that owns {@code location}. + */ + public static void runAt(Location location, Runnable task) { + JavaPlugin p = requirePluginForFolia(); + if (p != null && location != null && location.getWorld() != null) { + SchedulerFactory.getScheduler().runTask(p, location, task); + return; + } + if (p != null) { + SchedulerFactory.getScheduler().runTask(p, task); + return; + } + task.run(); + } + + /** + * Runs {@code task} on the global region / main thread. + */ + public static void runGlobal(Runnable task) { + JavaPlugin p = requirePluginForFolia(); + if (p != null) { + SchedulerFactory.getScheduler().runTask(p, task); + return; + } + task.run(); + } + + /** + * Runs {@code task} off the tick threads (Folia {@code AsyncScheduler} / Bukkit async). + */ + public static void runAsync(Runnable task) { + JavaPlugin p = requirePluginForFolia(); + if (p != null) { + SchedulerFactory.getScheduler().runTaskAsynchronously(p, task); + return; + } + LEGACY_FALLBACK.execute(task); + } + + /** + * Delayed entity-owned execution used by NMS wrappers when reopening a sign (~4 ticks ≈ 200ms). + */ + public static void runLater(Player player, Location location, Runnable task, long delayTicks) { + long delay = Math.max(1L, delayTicks); + JavaPlugin p = plugin; + de.rapha149.signgui.util.SchedulerAdapter scheduler = SchedulerFactory.getScheduler(); + + if (p != null && player != null && player.isOnline()) { + scheduler.runTaskLater(p, player, task, delay); + return; + } + if (p != null && location != null && location.getWorld() != null) { + scheduler.runTaskLater(p, location, task, delay); + return; + } + if (p != null) { + scheduler.runTaskLater(p, task, delay); + return; + } + + if (PlatformDetector.isFolia()) { + throw new IllegalStateException( + "SignGUI on Folia requires callHandlerSynchronously(plugin) so delayed opens can use the entity scheduler."); + } + + LEGACY_FALLBACK.schedule(task, delay * 50L, TimeUnit.MILLISECONDS); + } + + private static JavaPlugin requirePluginForFolia() { + JavaPlugin p = plugin; + if (p == null && PlatformDetector.isFolia()) { + throw new IllegalStateException( + "SignGUI on Folia requires callHandlerSynchronously(plugin) (or SignGUIScheduler.setPlugin)."); + } + return p; + } +} diff --git a/api/src/main/java/de/rapha149/signgui/util/scheduler/BukkitSchedulerAdapter.java b/api/src/main/java/de/rapha149/signgui/util/scheduler/BukkitSchedulerAdapter.java new file mode 100644 index 00000000..95e97413 --- /dev/null +++ b/api/src/main/java/de/rapha149/signgui/util/scheduler/BukkitSchedulerAdapter.java @@ -0,0 +1,62 @@ +package de.rapha149.signgui.util.scheduler; + +import de.rapha149.signgui.util.SchedulerAdapter; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.plugin.java.JavaPlugin; + +/** + * Standard Bukkit/Spigot/Paper scheduler implementation. + * Also used for CanvasMC and Archlight which are compatible with Bukkit API. + */ +public class BukkitSchedulerAdapter implements SchedulerAdapter { + + @Override + public void runTask(JavaPlugin plugin, Runnable task) { + if (Bukkit.isPrimaryThread()) { + task.run(); + } else { + Bukkit.getScheduler().runTask(plugin, task); + } + } + + @Override + public void runTask(JavaPlugin plugin, Entity entity, Runnable task) { + runTask(plugin, task); + } + + @Override + public void runTask(JavaPlugin plugin, Location location, Runnable task) { + runTask(plugin, task); + } + + @Override + public void runTaskAsynchronously(JavaPlugin plugin, Runnable task) { + if (Bukkit.isPrimaryThread()) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, task); + } else { + task.run(); + } + } + + @Override + public void runTaskLater(JavaPlugin plugin, Runnable task, long delayTicks) { + Bukkit.getScheduler().runTaskLater(plugin, task, delayTicks); + } + + @Override + public void runTaskLater(JavaPlugin plugin, Entity entity, Runnable task, long delayTicks) { + runTaskLater(plugin, task, delayTicks); + } + + @Override + public void runTaskLater(JavaPlugin plugin, Location location, Runnable task, long delayTicks) { + runTaskLater(plugin, task, delayTicks); + } + + @Override + public boolean isOnMainThread() { + return Bukkit.isPrimaryThread(); + } +} diff --git a/api/src/main/java/de/rapha149/signgui/util/scheduler/FoliaSchedulerAdapter.java b/api/src/main/java/de/rapha149/signgui/util/scheduler/FoliaSchedulerAdapter.java new file mode 100644 index 00000000..458eeac8 --- /dev/null +++ b/api/src/main/java/de/rapha149/signgui/util/scheduler/FoliaSchedulerAdapter.java @@ -0,0 +1,218 @@ +package de.rapha149.signgui.util.scheduler; + +import de.rapha149.signgui.util.PlatformDetector; +import de.rapha149.signgui.util.SchedulerAdapter; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.plugin.java.JavaPlugin; + +import java.lang.reflect.Method; +import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Region-aware scheduler for Folia and modern Paper. + *

+ * Uses reflection so the API module can still compile against older Spigot baselines + * while calling {@code EntityScheduler} / {@code RegionScheduler} / + * {@code GlobalRegionScheduler} / {@code AsyncScheduler} at runtime. + *

+ * On Folia, never falls back to {@link BukkitSchedulerAdapter} (that API is unsafe there). + */ +public class FoliaSchedulerAdapter implements SchedulerAdapter { + + private static final Logger LOGGER = Logger.getLogger("SignGUI"); + + private static final Method GET_REGION_SCHEDULER; + private static final Method GET_GLOBAL_REGION_SCHEDULER; + private static final Method GET_ASYNC_SCHEDULER; + private static final Method REGION_EXECUTE; + private static final Method REGION_RUN_DELAYED; + private static final Method GLOBAL_RUN; + private static final Method GLOBAL_RUN_DELAYED; + private static final Method ASYNC_RUN_NOW; + private static final Method ENTITY_GET_SCHEDULER; + private static final Method ENTITY_EXECUTE; + private static final Method ENTITY_RUN_DELAYED; + private static final Method IS_OWNED_BY_CURRENT_REGION; + private static final boolean AVAILABLE; + + static { + Method getRegionScheduler = null; + Method getGlobalRegionScheduler = null; + Method getAsyncScheduler = null; + Method regionExecute = null; + Method regionRunDelayed = null; + Method globalRun = null; + Method globalRunDelayed = null; + Method asyncRunNow = null; + Method entityGetScheduler = null; + Method entityExecute = null; + Method entityRunDelayed = null; + Method isOwnedByCurrentRegion = null; + boolean available = false; + + try { + Class regionSchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.RegionScheduler"); + Class globalRegionSchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler"); + Class entitySchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler"); + Class asyncSchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.AsyncScheduler"); + + Class serverClass = org.bukkit.Server.class; + getRegionScheduler = serverClass.getMethod("getRegionScheduler"); + getGlobalRegionScheduler = serverClass.getMethod("getGlobalRegionScheduler"); + getAsyncScheduler = serverClass.getMethod("getAsyncScheduler"); + + regionExecute = regionSchedulerClass.getMethod("execute", org.bukkit.plugin.Plugin.class, Location.class, Runnable.class); + regionRunDelayed = regionSchedulerClass.getMethod("runDelayed", org.bukkit.plugin.Plugin.class, Location.class, + Consumer.class, long.class); + globalRun = globalRegionSchedulerClass.getMethod("run", org.bukkit.plugin.Plugin.class, Consumer.class); + globalRunDelayed = globalRegionSchedulerClass.getMethod("runDelayed", org.bukkit.plugin.Plugin.class, + Consumer.class, long.class); + asyncRunNow = asyncSchedulerClass.getMethod("runNow", org.bukkit.plugin.Plugin.class, Consumer.class); + + entityGetScheduler = Entity.class.getMethod("getScheduler"); + entityExecute = entitySchedulerClass.getMethod("execute", org.bukkit.plugin.Plugin.class, Runnable.class, + Runnable.class, long.class); + entityRunDelayed = entitySchedulerClass.getMethod("runDelayed", org.bukkit.plugin.Plugin.class, + Consumer.class, Runnable.class, long.class); + + try { + Class regionizedServerClass = Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); + isOwnedByCurrentRegion = regionizedServerClass.getMethod("isOwnedByCurrentRegion", Location.class); + } catch (ClassNotFoundException | NoSuchMethodException ignored) { + // Paper without Folia still exposes region schedulers; ownership check is Folia-only. + } + + available = true; + } catch (ReflectiveOperationException e) { + LOGGER.log(Level.WARNING, "SignGUI: Paper/Folia region schedulers unavailable: " + e.getMessage()); + } + + GET_REGION_SCHEDULER = getRegionScheduler; + GET_GLOBAL_REGION_SCHEDULER = getGlobalRegionScheduler; + GET_ASYNC_SCHEDULER = getAsyncScheduler; + REGION_EXECUTE = regionExecute; + REGION_RUN_DELAYED = regionRunDelayed; + GLOBAL_RUN = globalRun; + GLOBAL_RUN_DELAYED = globalRunDelayed; + ASYNC_RUN_NOW = asyncRunNow; + ENTITY_GET_SCHEDULER = entityGetScheduler; + ENTITY_EXECUTE = entityExecute; + ENTITY_RUN_DELAYED = entityRunDelayed; + IS_OWNED_BY_CURRENT_REGION = isOwnedByCurrentRegion; + AVAILABLE = available; + } + + public static boolean isAvailable() { + return AVAILABLE; + } + + @Override + public void runTask(JavaPlugin plugin, Runnable task) { + try { + Object globalScheduler = GET_GLOBAL_REGION_SCHEDULER.invoke(Bukkit.getServer()); + GLOBAL_RUN.invoke(globalScheduler, plugin, (Consumer) scheduledTask -> safeRun(task)); + } catch (ReflectiveOperationException e) { + handleFailure(plugin, "global run", e, task); + } + } + + @Override + public void runTask(JavaPlugin plugin, Entity entity, Runnable task) { + try { + Object entityScheduler = ENTITY_GET_SCHEDULER.invoke(entity); + // delay=0 runs immediately when the current region owns the entity. + ENTITY_EXECUTE.invoke(entityScheduler, plugin, (Runnable) () -> safeRun(task), null, 0L); + } catch (ReflectiveOperationException e) { + handleFailure(plugin, "entity run", e, task); + } + } + + @Override + public void runTask(JavaPlugin plugin, Location location, Runnable task) { + try { + if (IS_OWNED_BY_CURRENT_REGION != null) { + boolean owned = (boolean) IS_OWNED_BY_CURRENT_REGION.invoke(null, location); + if (owned) { + safeRun(task); + return; + } + } + Object regionScheduler = GET_REGION_SCHEDULER.invoke(Bukkit.getServer()); + REGION_EXECUTE.invoke(regionScheduler, plugin, location, (Runnable) () -> safeRun(task)); + } catch (ReflectiveOperationException e) { + handleFailure(plugin, "region run", e, task); + } + } + + @Override + public void runTaskAsynchronously(JavaPlugin plugin, Runnable task) { + try { + Object asyncScheduler = GET_ASYNC_SCHEDULER.invoke(Bukkit.getServer()); + ASYNC_RUN_NOW.invoke(asyncScheduler, plugin, (Consumer) scheduledTask -> safeRun(task)); + } catch (ReflectiveOperationException e) { + handleFailure(plugin, "async run", e, task); + } + } + + @Override + public void runTaskLater(JavaPlugin plugin, Runnable task, long delayTicks) { + try { + Object globalScheduler = GET_GLOBAL_REGION_SCHEDULER.invoke(Bukkit.getServer()); + GLOBAL_RUN_DELAYED.invoke(globalScheduler, plugin, + (Consumer) scheduledTask -> safeRun(task), Math.max(1L, delayTicks)); + } catch (ReflectiveOperationException e) { + handleFailure(plugin, "global delayed run", e, task); + } + } + + @Override + public void runTaskLater(JavaPlugin plugin, Entity entity, Runnable task, long delayTicks) { + try { + Object entityScheduler = ENTITY_GET_SCHEDULER.invoke(entity); + ENTITY_RUN_DELAYED.invoke(entityScheduler, plugin, + (Consumer) scheduledTask -> safeRun(task), null, Math.max(1L, delayTicks)); + } catch (ReflectiveOperationException e) { + handleFailure(plugin, "entity delayed run", e, task); + } + } + + @Override + public void runTaskLater(JavaPlugin plugin, Location location, Runnable task, long delayTicks) { + try { + Object regionScheduler = GET_REGION_SCHEDULER.invoke(Bukkit.getServer()); + REGION_RUN_DELAYED.invoke(regionScheduler, plugin, location, + (Consumer) scheduledTask -> safeRun(task), Math.max(1L, delayTicks)); + } catch (ReflectiveOperationException e) { + handleFailure(plugin, "region delayed run", e, task); + } + } + + @Override + public boolean isOnMainThread() { + return Bukkit.isPrimaryThread(); + } + + private static void safeRun(Runnable task) { + try { + task.run(); + } catch (Throwable t) { + LOGGER.log(Level.SEVERE, "SignGUI scheduled task failed", t); + } + } + + private void handleFailure(JavaPlugin plugin, String what, Exception e, Runnable task) { + LOGGER.log(Level.SEVERE, "SignGUI failed Folia/Paper " + what, e); + if (PlatformDetector.isFolia()) { + throw new IllegalStateException("SignGUI cannot fall back to BukkitScheduler on Folia (" + what + ")", e); + } + if (plugin != null) { + new BukkitSchedulerAdapter().runTask(plugin, task); + } else { + safeRun(task); + } + } +} diff --git a/api/src/main/java/de/rapha149/signgui/util/scheduler/SchedulerFactory.java b/api/src/main/java/de/rapha149/signgui/util/scheduler/SchedulerFactory.java new file mode 100644 index 00000000..b8b3d9c6 --- /dev/null +++ b/api/src/main/java/de/rapha149/signgui/util/scheduler/SchedulerFactory.java @@ -0,0 +1,35 @@ +package de.rapha149.signgui.util.scheduler; + +import de.rapha149.signgui.util.PlatformDetector; +import de.rapha149.signgui.util.SchedulerAdapter; + +/** + * Provides the platform-appropriate {@link SchedulerAdapter}. + *

+ * Prefers Paper/Folia region schedulers whenever {@code RegionScheduler} is present + * (covers Folia and modern Paper). Falls back to the Bukkit scheduler otherwise. + */ +public final class SchedulerFactory { + + private static volatile SchedulerAdapter cachedAdapter; + + private SchedulerFactory() { + } + + public static SchedulerAdapter getScheduler() { + SchedulerAdapter adapter = cachedAdapter; + if (adapter != null) { + return adapter; + } + synchronized (SchedulerFactory.class) { + if (cachedAdapter == null) { + if (PlatformDetector.hasRegionScheduler() && FoliaSchedulerAdapter.isAvailable()) { + cachedAdapter = new FoliaSchedulerAdapter(); + } else { + cachedAdapter = new BukkitSchedulerAdapter(); + } + } + return cachedAdapter; + } + } +} diff --git a/api/src/main/java/de/rapha149/signgui/version/ProtocolProbe.java b/api/src/main/java/de/rapha149/signgui/version/ProtocolProbe.java new file mode 100644 index 00000000..437474bc --- /dev/null +++ b/api/src/main/java/de/rapha149/signgui/version/ProtocolProbe.java @@ -0,0 +1,278 @@ +package de.rapha149.signgui.version; + +import de.rapha149.signgui.exception.SignGUIVersionException; +import org.bukkit.Bukkit; + +/** + * Probes the running server's Minecraft protocol version. + *

+ * Prefers {@code SharedConstants}, then CraftBukkit package mapping, then Bukkit version string. + */ +public final class ProtocolProbe { + + private ProtocolProbe() { + } + + /** + * @return the current protocol version + * @throws SignGUIVersionException if the protocol cannot be determined + */ + public static int current() throws SignGUIVersionException { + Integer fromShared = fromSharedConstants(); + if (fromShared != null) { + return fromShared; + } + + Integer fromPackage = fromCraftBukkitPackage(); + if (fromPackage != null) { + return fromPackage; + } + + Integer fromBukkit = fromBukkitVersion(); + if (fromBukkit != null) { + return fromBukkit; + } + + throw new SignGUIVersionException("Cannot probe protocol version"); + } + + private static Integer fromSharedConstants() { + try { + Class shared = Class.forName("net.minecraft.SharedConstants"); + Object version = shared.getMethod("getCurrentVersion").invoke(null); + try { + Object protocol = version.getClass().getMethod("getProtocolVersion").invoke(version); + if (protocol instanceof Integer) { + return (Integer) protocol; + } + } catch (NoSuchMethodException ignored) { + } + try { + Object protocol = version.getClass().getMethod("protocolVersion").invoke(version); + if (protocol instanceof Integer) { + return (Integer) protocol; + } + } catch (NoSuchMethodException ignored) { + } + } catch (Throwable ignored) { + } + return null; + } + + private static Integer fromCraftBukkitPackage() { + try { + String pkg = Bukkit.getServer().getClass().getPackage().getName(); + int idx = pkg.lastIndexOf('.'); + if (idx >= 0) { + return mapLegacyPackage(pkg.substring(idx + 1)); + } + } catch (Throwable ignored) { + } + return null; + } + + private static Integer fromBukkitVersion() { + try { + String version = normalizeMinecraftVersion(Bukkit.getBukkitVersion()); + Integer exact = mapMinecraftVersion(version); + if (exact != null) { + return exact; + } + int lastDot = version.lastIndexOf('.'); + int firstDot = version.indexOf('.'); + if (lastDot > firstDot) { + return mapMinecraftVersion(version.substring(0, lastDot)); + } + } catch (Throwable ignored) { + } + return null; + } + + private static String normalizeMinecraftVersion(String bukkitVersion) { + String version = bukkitVersion; + int dash = version.indexOf('-'); + if (dash >= 0) { + version = version.substring(0, dash); + } + int buildIdx = version.indexOf(".build."); + if (buildIdx >= 0) { + version = version.substring(0, buildIdx); + } + return version; + } + + private static Integer mapMinecraftVersion(String version) { + if (version == null) { + return null; + } + switch (version) { + case "1.8": + case "1.8.3": + case "1.8.4": + case "1.8.5": + case "1.8.6": + case "1.8.7": + case "1.8.8": + case "1.8.9": + return ProtocolVersions.V1_8; + case "1.9": + case "1.9.2": + return ProtocolVersions.V1_9; + case "1.9.4": + return ProtocolVersions.V1_9_4; + case "1.10": + case "1.10.2": + return ProtocolVersions.V1_10; + case "1.11": + case "1.11.2": + return ProtocolVersions.V1_11; + case "1.12": + case "1.12.2": + return ProtocolVersions.V1_12_2; + case "1.13": + case "1.13.1": + return ProtocolVersions.V1_13; + case "1.13.2": + return ProtocolVersions.V1_13_2; + case "1.14": + case "1.14.4": + return ProtocolVersions.V1_14_4; + case "1.15": + case "1.15.2": + return ProtocolVersions.V1_15_2; + case "1.16": + case "1.16.1": + return ProtocolVersions.V1_16_1; + case "1.16.2": + case "1.16.3": + return ProtocolVersions.V1_16_3; + case "1.16.4": + case "1.16.5": + return ProtocolVersions.V1_16_4; + case "1.17": + case "1.17.1": + return ProtocolVersions.V1_17_1; + case "1.18": + case "1.18.1": + return ProtocolVersions.V1_18; + case "1.18.2": + return ProtocolVersions.V1_18_2; + case "1.19": + case "1.19.1": + case "1.19.2": + return ProtocolVersions.V1_19_1; + case "1.19.3": + return ProtocolVersions.V1_19_3; + case "1.19.4": + return ProtocolVersions.V1_19_4; + case "1.20": + case "1.20.1": + return ProtocolVersions.V1_20; + case "1.20.2": + return ProtocolVersions.V1_20_2; + case "1.20.3": + case "1.20.4": + return ProtocolVersions.V1_20_3; + case "1.20.5": + case "1.20.6": + return ProtocolVersions.V1_20_5; + case "1.21": + case "1.21.1": + return ProtocolVersions.V1_21; + case "1.21.2": + case "1.21.3": + return ProtocolVersions.V1_21_2; + case "1.21.4": + return ProtocolVersions.V1_21_4; + case "1.21.5": + return ProtocolVersions.V1_21_5; + case "1.21.6": + return ProtocolVersions.V1_21_6; + case "1.21.7": + case "1.21.8": + return ProtocolVersions.V1_21_7; + case "1.21.9": + case "1.21.10": + return ProtocolVersions.V1_21_9; + case "1.21.11": + return ProtocolVersions.V1_21_11; + case "26.1": + case "26.1.1": + case "26.1.2": + return ProtocolVersions.V26_1; + case "26.2": + return ProtocolVersions.V26_2; + default: + return null; + } + } + + private static Integer mapLegacyPackage(String nms) { + switch (nms) { + case "v1_8_R1": + case "v1_8_R2": + case "v1_8_R3": + return ProtocolVersions.V1_8; + case "v1_9_R1": + return ProtocolVersions.V1_9; + case "v1_9_R2": + return ProtocolVersions.V1_9_4; + case "v1_10_R1": + return ProtocolVersions.V1_10; + case "v1_11_R1": + return ProtocolVersions.V1_11; + case "v1_12_R1": + return ProtocolVersions.V1_12_2; + case "v1_13_R1": + return ProtocolVersions.V1_13; + case "v1_13_R2": + return ProtocolVersions.V1_13_2; + case "v1_14_R1": + return ProtocolVersions.V1_14_4; + case "v1_15_R1": + return ProtocolVersions.V1_15_2; + case "v1_16_R1": + return ProtocolVersions.V1_16_1; + case "v1_16_R2": + return ProtocolVersions.V1_16_3; + case "v1_16_R3": + return ProtocolVersions.V1_16_4; + case "v1_17_R1": + return ProtocolVersions.V1_17_1; + case "v1_18_R1": + return ProtocolVersions.V1_18; + case "v1_18_R2": + return ProtocolVersions.V1_18_2; + case "v1_19_R1": + return ProtocolVersions.V1_19_1; + case "v1_19_R2": + return ProtocolVersions.V1_19_3; + case "v1_19_R3": + return ProtocolVersions.V1_19_4; + case "v1_20_R1": + return ProtocolVersions.V1_20; + case "v1_20_R2": + return ProtocolVersions.V1_20_2; + case "v1_20_R3": + return ProtocolVersions.V1_20_3; + case "v1_20_R4": + return ProtocolVersions.V1_20_5; + case "v1_21_R1": + return ProtocolVersions.V1_21; + case "v1_21_R2": + return ProtocolVersions.V1_21_2; + case "v1_21_R3": + return ProtocolVersions.V1_21_4; + case "v1_21_R4": + return ProtocolVersions.V1_21_5; + case "v1_21_R5": + return ProtocolVersions.V1_21_6; + case "v1_21_R6": + return ProtocolVersions.V1_21_9; + case "v1_21_R7": + return ProtocolVersions.V1_21_11; + default: + return null; + } + } +} diff --git a/api/src/main/java/de/rapha149/signgui/version/ProtocolVersions.java b/api/src/main/java/de/rapha149/signgui/version/ProtocolVersions.java new file mode 100644 index 00000000..c72a15f8 --- /dev/null +++ b/api/src/main/java/de/rapha149/signgui/version/ProtocolVersions.java @@ -0,0 +1,182 @@ +package de.rapha149.signgui.version; + +/** + * Minecraft protocol version constants and NMS bucket ranges. + * Mirrors the PacketUxUi protocol map for SignGUI wrapper selection. + */ +public final class ProtocolVersions { + + public static final int V1_8 = 47; + public static final int V1_9 = 107; + public static final int V1_9_2 = 109; + public static final int V1_9_4 = 110; + public static final int V1_10 = 210; + public static final int V1_11 = 315; + public static final int V1_11_1 = 316; + public static final int V1_12 = 335; + public static final int V1_12_2 = 340; + public static final int V1_13 = 393; + public static final int V1_13_1 = 401; + public static final int V1_13_2 = 404; + public static final int V1_14 = 477; + public static final int V1_14_4 = 498; + public static final int V1_15 = 573; + public static final int V1_15_2 = 578; + public static final int V1_16 = 735; + public static final int V1_16_1 = 736; + public static final int V1_16_2 = 751; + public static final int V1_16_3 = 753; + public static final int V1_16_4 = 754; + public static final int V1_17 = 755; + public static final int V1_17_1 = 756; + public static final int V1_18 = 757; + public static final int V1_18_2 = 758; + public static final int V1_19 = 759; + public static final int V1_19_1 = 760; + public static final int V1_19_3 = 761; + public static final int V1_19_4 = 762; + public static final int V1_20 = 763; + public static final int V1_20_2 = 764; + public static final int V1_20_3 = 765; + public static final int V1_20_5 = 766; + public static final int V1_21 = 767; + public static final int V1_21_2 = 768; + public static final int V1_21_4 = 769; + public static final int V1_21_5 = 770; + public static final int V1_21_6 = 771; + public static final int V1_21_7 = 772; + public static final int V1_21_9 = 773; + public static final int V1_21_11 = 774; + public static final int V26_1 = 775; + public static final int V26_2 = 776; + + public static final int R1_8_R1_MIN = V1_8; + public static final int R1_8_R1_MAX = V1_8; + public static final int R1_8_R2_MIN = V1_8; + public static final int R1_8_R2_MAX = V1_8; + public static final int R1_8_R3_MIN = V1_8; + public static final int R1_8_R3_MAX = V1_8; + + public static final int R1_9_R1_MIN = V1_9; + public static final int R1_9_R1_MAX = V1_9_2; + public static final int R1_9_R2_MIN = V1_9_4; + public static final int R1_9_R2_MAX = V1_9_4; + + public static final int R1_10_R1_MIN = V1_10; + public static final int R1_10_R1_MAX = V1_10; + public static final int R1_11_R1_MIN = V1_11; + public static final int R1_11_R1_MAX = V1_11_1; + public static final int R1_12_R1_MIN = V1_12; + public static final int R1_12_R1_MAX = V1_12_2; + + public static final int R1_13_R1_MIN = V1_13; + public static final int R1_13_R1_MAX = V1_13_1; + public static final int R1_13_R2_MIN = V1_13_2; + public static final int R1_13_R2_MAX = V1_13_2; + + public static final int R1_14_R1_MIN = V1_14; + public static final int R1_14_R1_MAX = V1_14_4; + public static final int R1_15_R1_MIN = V1_15; + public static final int R1_15_R1_MAX = V1_15_2; + + public static final int R1_16_R1_MIN = V1_16; + public static final int R1_16_R1_MAX = V1_16_1; + public static final int R1_16_R2_MIN = V1_16_2; + public static final int R1_16_R2_MAX = V1_16_3; + public static final int R1_16_R3_MIN = V1_16_4; + public static final int R1_16_R3_MAX = V1_16_4; + + public static final int R1_17_R1_MIN = V1_17; + public static final int R1_17_R1_MAX = V1_17_1; + public static final int R1_18_R1_MIN = V1_18; + public static final int R1_18_R1_MAX = V1_18; + public static final int R1_18_R2_MIN = V1_18_2; + public static final int R1_18_R2_MAX = V1_18_2; + + public static final int R1_19_R1_MIN = V1_19; + public static final int R1_19_R1_MAX = V1_19_1; + public static final int R1_19_R2_MIN = V1_19_3; + public static final int R1_19_R2_MAX = V1_19_3; + public static final int R1_19_R3_MIN = V1_19_4; + public static final int R1_19_R3_MAX = V1_19_4; + + public static final int R1_20_R1_MIN = V1_20; + public static final int R1_20_R1_MAX = V1_20; + public static final int R1_20_R2_MIN = V1_20_2; + public static final int R1_20_R2_MAX = V1_20_2; + public static final int R1_20_R3_MIN = V1_20_3; + public static final int R1_20_R3_MAX = V1_20_3; + public static final int R1_20_R4_MIN = V1_20_5; + public static final int R1_20_R4_MAX = V1_20_5; + + public static final int R1_21_R1_MIN = V1_21; + public static final int R1_21_R1_MAX = V1_21; + public static final int R1_21_R2_MIN = V1_21_2; + public static final int R1_21_R2_MAX = V1_21_2; + public static final int R1_21_R3_MIN = V1_21_4; + public static final int R1_21_R3_MAX = V1_21_4; + public static final int R1_21_R4_MIN = V1_21_5; + public static final int R1_21_R4_MAX = V1_21_5; + public static final int R1_21_R5_MIN = V1_21_6; + public static final int R1_21_R5_MAX = V1_21_7; + public static final int R1_21_R6_MIN = V1_21_9; + public static final int R1_21_R6_MAX = V1_21_9; + public static final int R1_21_R7_MIN = V1_21_11; + public static final int R1_21_R7_MAX = V1_21_11; + + public static final int R26_1_MIN = V26_1; + public static final int R26_1_MAX = V26_1; + public static final int R26_2_MIN = V26_2; + public static final int R26_2_MAX = Integer.MAX_VALUE; + + private ProtocolVersions() { + } + + /** + * Resolves the NMS bucket id (without Mojang prefix) for a protocol version. + * + * @return bucket such as {@code 1_21_R5} or {@code 26_2}, or {@code null} if unsupported + */ + public static String bucketForProtocol(int protocol) { + // All 1.8.x share protocol 47; VersionMatcher refines R1/R2/R3 via package / Bukkit version. + if (in(protocol, R1_8_R1_MIN, R1_8_R3_MAX)) return "1_8_R3"; + if (in(protocol, R1_9_R1_MIN, R1_9_R1_MAX)) return "1_9_R1"; + if (in(protocol, R1_9_R2_MIN, R1_9_R2_MAX)) return "1_9_R2"; + if (in(protocol, R1_10_R1_MIN, R1_10_R1_MAX)) return "1_10_R1"; + if (in(protocol, R1_11_R1_MIN, R1_11_R1_MAX)) return "1_11_R1"; + if (in(protocol, R1_12_R1_MIN, R1_12_R1_MAX)) return "1_12_R1"; + if (in(protocol, R1_13_R1_MIN, R1_13_R1_MAX)) return "1_13_R1"; + if (in(protocol, R1_13_R2_MIN, R1_13_R2_MAX)) return "1_13_R2"; + if (in(protocol, R1_14_R1_MIN, R1_14_R1_MAX)) return "1_14_R1"; + if (in(protocol, R1_15_R1_MIN, R1_15_R1_MAX)) return "1_15_R1"; + if (in(protocol, R1_16_R1_MIN, R1_16_R1_MAX)) return "1_16_R1"; + if (in(protocol, R1_16_R2_MIN, R1_16_R2_MAX)) return "1_16_R2"; + if (in(protocol, R1_16_R3_MIN, R1_16_R3_MAX)) return "1_16_R3"; + if (in(protocol, R1_17_R1_MIN, R1_17_R1_MAX)) return "1_17_R1"; + if (in(protocol, R1_18_R1_MIN, R1_18_R1_MAX)) return "1_18_R1"; + if (in(protocol, R1_18_R2_MIN, R1_18_R2_MAX)) return "1_18_R2"; + if (in(protocol, R1_19_R1_MIN, R1_19_R1_MAX)) return "1_19_R1"; + if (in(protocol, R1_19_R2_MIN, R1_19_R2_MAX)) return "1_19_R2"; + if (in(protocol, R1_19_R3_MIN, R1_19_R3_MAX)) return "1_19_R3"; + if (in(protocol, R1_20_R1_MIN, R1_20_R1_MAX)) return "1_20_R1"; + if (in(protocol, R1_20_R2_MIN, R1_20_R2_MAX)) return "1_20_R2"; + if (in(protocol, R1_20_R3_MIN, R1_20_R3_MAX)) return "1_20_R3"; + if (in(protocol, R1_20_R4_MIN, R1_20_R4_MAX)) return "1_20_R4"; + if (in(protocol, R1_21_R1_MIN, R1_21_R1_MAX)) return "1_21_R1"; + if (in(protocol, R1_21_R2_MIN, R1_21_R2_MAX)) return "1_21_R2"; + if (in(protocol, R1_21_R3_MIN, R1_21_R3_MAX)) return "1_21_R3"; + if (in(protocol, R1_21_R4_MIN, R1_21_R4_MAX)) return "1_21_R4"; + if (in(protocol, R1_21_R5_MIN, R1_21_R5_MAX)) return "1_21_R5"; + if (in(protocol, R1_21_R6_MIN, R1_21_R6_MAX)) return "1_21_R6"; + // 1.21.10 shares R6 in Spigot; protocol may still be 773 + if (protocol == 773) return "1_21_R6"; + if (in(protocol, R1_21_R7_MIN, R1_21_R7_MAX)) return "1_21_R7"; + if (in(protocol, R26_1_MIN, R26_1_MAX)) return "26_1"; + if (protocol >= R26_2_MIN) return "26_2"; + return null; + } + + private static boolean in(int protocol, int min, int max) { + return protocol >= min && protocol <= max; + } +} diff --git a/api/src/main/java/de/rapha149/signgui/version/VersionMatcher.java b/api/src/main/java/de/rapha149/signgui/version/VersionMatcher.java index b4d0acff..0219a8ea 100644 --- a/api/src/main/java/de/rapha149/signgui/version/VersionMatcher.java +++ b/api/src/main/java/de/rapha149/signgui/version/VersionMatcher.java @@ -9,27 +9,88 @@ import java.util.Map; /** - * A utility class to get the version wrapper for the server version. + * Selects the version wrapper for the running server. + *

+ * Resolution order (PacketUxUi-style): + *

    + *
  1. Minecraft protocol version → NMS bucket
  2. + *
  3. CraftBukkit package ({@code v1_x_Ry}) when present — also used to disambiguate + * same-protocol buckets such as 1.8.x (protocol 47)
  4. + *
  5. Bukkit version string map for unversioned packages (26.x) / probe failures
  6. + *
*/ public class VersionMatcher { private static final Map VERSIONS; - private static final String NEWEST_VERSION = "1_21_R5"; + private static final String NEWEST_VERSION = "26_2"; private static boolean initialized; private static VersionWrapper wrapper; static { Map versions = new HashMap<>(); + versions.put("1.8", "1_8_R1"); + versions.put("1.8.3", "1_8_R2"); + versions.put("1.8.4", "1_8_R3"); + versions.put("1.8.5", "1_8_R3"); + versions.put("1.8.6", "1_8_R3"); + versions.put("1.8.7", "1_8_R3"); + versions.put("1.8.8", "1_8_R3"); + versions.put("1.8.9", "1_8_R3"); + versions.put("1.9", "1_9_R1"); + versions.put("1.9.2", "1_9_R1"); + versions.put("1.9.4", "1_9_R2"); + versions.put("1.10.2", "1_10_R1"); + versions.put("1.11", "1_11_R1"); + versions.put("1.11.2", "1_11_R1"); + versions.put("1.12", "1_12_R1"); + versions.put("1.12.2", "1_12_R1"); + versions.put("1.13", "1_13_R1"); + versions.put("1.13.1", "1_13_R1"); + versions.put("1.13.2", "1_13_R2"); + versions.put("1.14", "1_14_R1"); + versions.put("1.14.4", "1_14_R1"); + versions.put("1.15", "1_15_R1"); + versions.put("1.15.2", "1_15_R1"); + versions.put("1.16.1", "1_16_R1"); + versions.put("1.16.2", "1_16_R2"); + versions.put("1.16.3", "1_16_R2"); + versions.put("1.16.4", "1_16_R3"); + versions.put("1.16.5", "1_16_R3"); + versions.put("1.17", "1_17_R1"); + versions.put("1.17.1", "1_17_R1"); + versions.put("1.18", "1_18_R1"); + versions.put("1.18.1", "1_18_R1"); + versions.put("1.18.2", "1_18_R2"); + versions.put("1.19", "1_19_R1"); + versions.put("1.19.1", "1_19_R1"); + versions.put("1.19.2", "1_19_R1"); + versions.put("1.19.3", "1_19_R2"); + versions.put("1.19.4", "1_19_R3"); + versions.put("1.20", "1_20_R1"); + versions.put("1.20.1", "1_20_R1"); + versions.put("1.20.2", "1_20_R2"); + versions.put("1.20.3", "1_20_R3"); + versions.put("1.20.4", "1_20_R3"); versions.put("1.20.5", "1_20_R4"); versions.put("1.20.6", "1_20_R4"); + versions.put("1.21", "1_21_R1"); versions.put("1.21.1", "1_21_R1"); + versions.put("1.21.2", "1_21_R2"); versions.put("1.21.3", "1_21_R2"); versions.put("1.21.4", "1_21_R3"); versions.put("1.21.5", "1_21_R4"); versions.put("1.21.6", "1_21_R5"); versions.put("1.21.7", "1_21_R5"); versions.put("1.21.8", "1_21_R5"); + versions.put("1.21.9", "1_21_R6"); + versions.put("1.21.10", "1_21_R6"); + versions.put("1.21.11", "1_21_R7"); + // Year-based versions: CraftBukkit packages are unversioned. + versions.put("26.1", "26_1"); + versions.put("26.1.1", "26_1"); + versions.put("26.1.2", "26_1"); + versions.put("26.2", "26_2"); VERSIONS = Collections.unmodifiableMap(versions); } @@ -53,13 +114,8 @@ public static VersionWrapper getWrapper() throws SignGUIVersionException { } } - /** - * Internal method to initialize the version wrapper. - */ private static VersionWrapper initWrapper() throws SignGUIVersionException { - String craftBukkitPackage = Bukkit.getServer().getClass().getPackage().getName(); - String version = craftBukkitPackage.contains(".v") ? craftBukkitPackage.split("\\.")[3].substring(1) : - VERSIONS.getOrDefault(Bukkit.getBukkitVersion().split("-")[0], NEWEST_VERSION); + String version = resolveBucket(); final String className; if (useMojangMappings(version)) { @@ -78,7 +134,96 @@ private static VersionWrapper initWrapper() throws SignGUIVersionException { } } + /** + * Resolves the NMS bucket id for the running server (protocol-first). + */ + static String resolveBucket() throws SignGUIVersionException { + String packageBucket = craftBukkitPackageBucket(); + + try { + int protocol = ProtocolProbe.current(); + String byProtocol = ProtocolVersions.bucketForProtocol(protocol); + if (byProtocol != null) { + // Protocol 47 covers all 1.8.x CraftBukkit revisions — prefer package / version map. + if (protocol == ProtocolVersions.V1_8) { + if (packageBucket != null && packageBucket.startsWith("1_8_")) { + return packageBucket; + } + String fromBukkit = bucketFromBukkitVersion(); + if (fromBukkit != null && fromBukkit.startsWith("1_8_")) { + return fromBukkit; + } + } + return byProtocol; + } + } catch (SignGUIVersionException ignored) { + // fall through + } + + if (packageBucket != null) { + return packageBucket; + } + + String fromBukkit = bucketFromBukkitVersion(); + if (fromBukkit != null) { + return fromBukkit; + } + + return NEWEST_VERSION; + } + + /** + * @return CraftBukkit revision bucket such as {@code 1_21_R5}, or {@code null} when unversioned + */ + static String craftBukkitPackageBucket() { + String craftBukkitPackage = Bukkit.getServer().getClass().getPackage().getName(); + if (!craftBukkitPackage.contains(".v")) { + return null; + } + String[] parts = craftBukkitPackage.split("\\."); + if (parts.length >= 4 && parts[3].startsWith("v")) { + return parts[3].substring(1); + } + return null; + } + + static String bucketFromBukkitVersion() { + String minecraftVersion = normalizeMinecraftVersion(Bukkit.getBukkitVersion()); + String mapped = VERSIONS.get(minecraftVersion); + if (mapped != null) { + return mapped; + } + + int lastDot = minecraftVersion.lastIndexOf('.'); + int firstDot = minecraftVersion.indexOf('.'); + if (lastDot > firstDot) { + mapped = VERSIONS.get(minecraftVersion.substring(0, lastDot)); + if (mapped != null) { + return mapped; + } + } + return null; + } + + static String normalizeMinecraftVersion(String bukkitVersion) { + String version = bukkitVersion; + int dash = version.indexOf('-'); + if (dash >= 0) { + version = version.substring(0, dash); + } + int buildIdx = version.indexOf(".build."); + if (buildIdx >= 0) { + version = version.substring(0, buildIdx); + } + return version; + } + private static boolean useMojangMappings(String version) { + // Year-based buckets (26.x+): Spigot and Paper both ship Mojang-mapped servers. + if (!version.startsWith("1_")) { + return true; + } + try { Class.forName("com.destroystokyo.paper.ParticleBuilder"); } catch (ClassNotFoundException ignored) { @@ -88,8 +233,9 @@ private static boolean useMojangMappings(String version) { final String[] versionNumbers = version.replace("R", "").split("_"); int major = Integer.parseInt(versionNumbers[1]); int minor = versionNumbers.length > 2 ? Integer.parseInt(versionNumbers[2]) : 0; - if (major == 20 && minor == 4) + if (major == 20 && minor == 4) { return true; // 1.20.5/6 + } return major > 20; // >= 1.21 } } diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts new file mode 100644 index 00000000..440f0a29 --- /dev/null +++ b/build-logic/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + `kotlin-dsl` +} + +repositories { + gradlePluginPortal() + maven("https://repo.papermc.io/repository/maven-public/") +} + +dependencies { + implementation(libs.paperweight.userdev) +} diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 00000000..aa5e146f --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,9 @@ +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} + +rootProject.name = "build-logic" diff --git a/build-logic/src/main/kotlin/module-java-versions.gradle.kts b/build-logic/src/main/kotlin/module-java-versions.gradle.kts new file mode 100644 index 00000000..9ef03502 --- /dev/null +++ b/build-logic/src/main/kotlin/module-java-versions.gradle.kts @@ -0,0 +1,61 @@ +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.jvm.toolchain.JavaLanguageVersion +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.withType + +plugins { + `java-library` +} + +val modulesJava16 = setOf("1_17_R1") + +val modulesJava17 = setOf( + "1_18_R1", "1_18_R2", + "1_19_R1", "1_19_R2", "1_19_R3", + "1_20_R1", "1_20_R2", "1_20_R3", +) + +val modulesJava21 = setOf( + "1_20_R4", + "1_21_R1", "1_21_R2", "1_21_R3", "1_21_R4", "1_21_R5", "1_21_R6", "1_21_R7", + "Mojang1_20_R4", + "Mojang1_21_R1", "Mojang1_21_R2", "Mojang1_21_R3", "Mojang1_21_R4", "Mojang1_21_R5", + "Mojang1_21_R6", "Mojang1_21_R7", + "api", +) + +val modulesJava25 = setOf( + "Mojang26_1", "Mojang26_2", +) + +// Shared by every Spigot/Mojang bucket (including Java 8). Compile with a modern +// toolchain so Spigot 1.17+ jars are readable, but emit Java 8 bytecode / attributes. +val sharedApiJava8 = setOf("wrapper") + +configure { + toolchain { + val version = when (project.name) { + in sharedApiJava8 -> 21 + in modulesJava25 -> 25 + in modulesJava21 -> 21 + in modulesJava17 -> 17 + in modulesJava16 -> 16 + else -> 8 + } + languageVersion.set(JavaLanguageVersion.of(version)) + } +} + +tasks.withType().configureEach { + options.encoding = "UTF-8" + // --release needs javac 9+; Java 8 toolchains inherit bytecode level from the toolchain. + when (project.name) { + in sharedApiJava8 -> options.release.set(8) + // Must match toolchain: paper-api 26.x requires JVM 25 attributes. + in modulesJava25 -> options.release.set(25) + in modulesJava21 -> options.release.set(21) + in modulesJava17 -> options.release.set(17) + in modulesJava16 -> options.release.set(16) + } +} diff --git a/build-logic/src/main/kotlin/papermc-mojang.gradle.kts b/build-logic/src/main/kotlin/papermc-mojang.gradle.kts new file mode 100644 index 00000000..8be29b30 --- /dev/null +++ b/build-logic/src/main/kotlin/papermc-mojang.gradle.kts @@ -0,0 +1,83 @@ +import io.papermc.paperweight.userdev.ReobfArtifactConfiguration +import util.mojangEra +import util.paperDevBundleVersion + +plugins { + id("module-java-versions") + id("io.papermc.paperweight.userdev") +} + +repositories { + mavenCentral() + maven("https://repo.papermc.io/repository/maven-public/") +} + +val bundleVersion = paperDevBundleVersion() + +dependencies { + paperweight.paperDevBundle(bundleVersion) + // paperweight's mapped server alone is not always enough for Bukkit/Netty API compile. + compileOnly("io.papermc.paper:paper-api:$bundleVersion") + compileOnly("io.netty:netty-transport:4.1.118.Final") + compileOnly("io.netty:netty-handler:4.1.118.Final") + compileOnly(project(":wrapper")) +} + +paperweight.reobfArtifactConfiguration = ReobfArtifactConfiguration.MOJANG_PRODUCTION + +tasks.matching { it.name == "reobfJar" }.configureEach { + enabled = false +} + +configurations.configureEach { + if (name.contains("reobf", ignoreCase = true)) { + outgoing.artifacts.clear() + outgoing.artifact(tasks.named("jar")) + } +} + +tasks.jar { + archiveClassifier.set("") +} + +val eraDirName = mojangEra() +if (eraDirName != null) { + val sharedOut = layout.buildDirectory.dir("generated-shared") + val bucketSuffix = project.name.removePrefix("Mojang") + val wrapperClassName = "MojangWrapper$bucketSuffix" + + val prepareSharedSources = tasks.register("prepareSharedSources") { + val srcRoot = rootProject.file("$eraDirName/src/main/java") + inputs.dir(srcRoot) + inputs.property("wrapperClassName", wrapperClassName) + outputs.dir(sharedOut) + doLast { + val outRoot = sharedOut.get().asFile + outRoot.deleteRecursively() + val fromDir = File(srcRoot, "de/rapha149/signgui/version") + if (!fromDir.isDirectory) { + throw GradleException("Missing shared sources: ${fromDir.absolutePath}") + } + fromDir.walkTopDown().filter { it.isFile && it.extension == "java" }.forEach { file -> + val destName = file.name.replace("MojangWrapperShared", wrapperClassName) + val dest = File(outRoot, "de/rapha149/signgui/version/$destName") + dest.parentFile.mkdirs() + dest.writeText(file.readText().replace("MojangWrapperShared", wrapperClassName)) + } + } + } + + sourceSets.named("main") { + java { + setSrcDirs(listOf(sharedOut, file("src/main/java"))) + } + } + + tasks.named("compileJava") { + dependsOn(prepareSharedSources) + } + + tasks.named("jar") { + dependsOn(prepareSharedSources) + } +} diff --git a/build-logic/src/main/kotlin/spigot.gradle.kts b/build-logic/src/main/kotlin/spigot.gradle.kts new file mode 100644 index 00000000..a8fa7697 --- /dev/null +++ b/build-logic/src/main/kotlin/spigot.gradle.kts @@ -0,0 +1,25 @@ +import util.mcVersion + +plugins { + id("module-java-versions") +} + +repositories { + // CodeMC fat NMS jars must win over Spigot Hub POM-only artifacts (e.g. 1.21.1). + exclusiveContent { + forRepository { + maven("https://repo.codemc.io/repository/nms/") + } + forRepository { + maven("https://repo.codemc.org/repository/nms/") + } + filter { + includeModule("org.spigotmc", "spigot") + } + } +} + +dependencies { + compileOnly("org.spigotmc:spigot:${mcVersion()}-R0.1-SNAPSHOT") + compileOnly(project(":wrapper")) +} diff --git a/build-logic/src/main/kotlin/util/Mappings.kt b/build-logic/src/main/kotlin/util/Mappings.kt new file mode 100644 index 00000000..c73dabb1 --- /dev/null +++ b/build-logic/src/main/kotlin/util/Mappings.kt @@ -0,0 +1,83 @@ +package util + +import org.gradle.api.Project + +/** + * Exact Spigot NMS versions the wrappers were written against (from pre-Gradle Maven POMs). + * Patch mismatches (e.g. 1.18 vs 1.18.1) change obfuscation and break compilation. + */ +private val spigotVersions = mapOf( + "1_8_R1" to "1.8", + "1_8_R2" to "1.8.3", + "1_8_R3" to "1.8.8", + "1_9_R1" to "1.9", + "1_9_R2" to "1.9.4", + "1_10_R1" to "1.10.2", + "1_11_R1" to "1.11", + "1_12_R1" to "1.12", + "1_13_R1" to "1.13", + "1_13_R2" to "1.13.1", + "1_14_R1" to "1.14", + "1_15_R1" to "1.15", + "1_16_R1" to "1.16.1", + "1_16_R2" to "1.16.2", + "1_16_R3" to "1.16.4", + "1_17_R1" to "1.17", + "1_18_R1" to "1.18", + "1_18_R2" to "1.18.2", + "1_19_R1" to "1.19", + "1_19_R2" to "1.19.3", + "1_19_R3" to "1.19.4", + "1_20_R1" to "1.20", + "1_20_R2" to "1.20.2", + "1_20_R3" to "1.20.3", + "1_20_R4" to "1.20.5", + "1_21_R1" to "1.21.1", + "1_21_R2" to "1.21.3", + "1_21_R3" to "1.21.4", + "1_21_R4" to "1.21.5", + "1_21_R5" to "1.21.6", + "1_21_R6" to "1.21.10", + "1_21_R7" to "1.21.11", + "26_1" to "26.1.2", + "26_2" to "26.2", +) + +/** Paperweight / Spigot Maven version for the current NMS module project name. */ +fun Project.mcVersion(): String { + val projectName = project.name.replace("Mojang", "") + return spigotVersions[projectName] + ?: error("No mcVersion mapping for project '${project.name}'") +} + +/** Paperweight paperDevBundle coordinate version (may differ slightly from Spigot). */ +fun Project.paperDevBundleVersion(): String { + val projectName = project.name.replace("Mojang", "") + return when (projectName) { + "1_20_R4" -> "1.20.6-R0.1-SNAPSHOT" + "1_21_R1" -> "1.21.1-R0.1-SNAPSHOT" + "1_21_R2" -> "1.21.3-R0.1-SNAPSHOT" + "1_21_R3" -> "1.21.4-R0.1-SNAPSHOT" + "1_21_R4" -> "1.21.5-R0.1-SNAPSHOT" + // Paper-nms used 1.21.6; 1.21.7/1.21.8 share the same CraftBukkit revision. + "1_21_R5" -> "1.21.8-R0.1-SNAPSHOT" + "1_21_R6" -> "1.21.10-R0.1-SNAPSHOT" + "1_21_R7" -> "1.21.11-R0.1-SNAPSHOT" + "26_1" -> "26.1.2.build.+" + "26_2" -> "26.2.build.+" + else -> "${mcVersion()}-R0.1-SNAPSHOT" + } +} + +/** + * Shared Mojang era directory for this module, or null when the module keeps hand-written sources + * (API differences such as pale oak / early 1.21). + */ +fun Project.mojangEra(): String? { + return when (project.name) { + "Mojang26_1", "Mojang26_2" -> "shared-mojang-26" + "Mojang1_21_R2", "Mojang1_21_R3", "Mojang1_21_R4", "Mojang1_21_R5", + "Mojang1_21_R6", "Mojang1_21_R7" -> "shared-mojang-modern" + else -> null + } +} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 00000000..31b1f5ad --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,187 @@ +plugins { + `java-library` + alias(libs.plugins.shadow) + `maven-publish` +} + +allprojects { + group = rootProject.property("group") as String + version = rootProject.property("version") as String + + repositories { + mavenCentral() + mavenLocal() + maven("https://repo.papermc.io/repository/maven-public/") + // Prefer CodeMC NMS jars over Spigot Hub POM-only coordinates. + maven("https://repo.codemc.io/repository/nms/") + maven("https://repo.codemc.org/repository/nms/") + maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") + } +} + +val spigotBuckets = listOf( + "1_8_R1", "1_8_R2", "1_8_R3", + "1_9_R1", "1_9_R2", + "1_10_R1", + "1_11_R1", + "1_12_R1", + "1_13_R1", "1_13_R2", + "1_14_R1", + "1_15_R1", + "1_16_R1", "1_16_R2", "1_16_R3", + "1_17_R1", + "1_18_R1", "1_18_R2", + "1_19_R1", "1_19_R2", "1_19_R3", + "1_20_R1", "1_20_R2", "1_20_R3", "1_20_R4", + "1_21_R1", "1_21_R2", "1_21_R3", "1_21_R4", "1_21_R5", "1_21_R6", "1_21_R7", +) + +val mojangBuckets = listOf( + "Mojang1_20_R4", + "Mojang1_21_R1", "Mojang1_21_R2", "Mojang1_21_R3", "Mojang1_21_R4", "Mojang1_21_R5", + "Mojang1_21_R6", "Mojang1_21_R7", + "Mojang26_1", "Mojang26_2", +) + +dependencies { + implementation(project(":wrapper")) + implementation(project(":api")) + spigotBuckets.forEach { implementation(project(":$it")) } + mojangBuckets.forEach { implementation(project(":$it")) } +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } +} + +tasks.jar { + enabled = false + dependsOn(tasks.shadowJar) +} + +tasks.shadowJar { + archiveBaseName.set("signgui") + archiveClassifier.set("") + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + exclude( + "META-INF/*.SF", + "META-INF/*.DSA", + "META-INF/*.RSA", + "META-INF/maven/**", + ) + mergeServiceFiles() +} + +listOf("apiElements", "runtimeElements").forEach { configName -> + configurations.named(configName).configure { + outgoing.artifacts.clear() + outgoing.artifact(tasks.shadowJar) + } +} + +tasks.build { + dependsOn(tasks.shadowJar) +} + +publishing { + publications { + create("maven") { + artifactId = "signgui" + artifact(tasks.shadowJar) { + classifier = null + } + pom { + name.set("SignGUI") + description.set("An api to get input text via a sign in Minecraft (1.8–26.x).") + url.set("https://github.com/OPmasterLEO/SignGUI") + licenses { + license { + name.set("MIT License") + url.set("http://www.opensource.org/licenses/mit-license.php") + } + } + developers { + developer { + id.set("rapha149") + name.set("Rapha149") + } + developer { + id.set("opmasterleo") + name.set("OPmasterLEO") + } + } + withXml { + asNode().appendNode("dependencies") + } + } + } + } + repositories { + fun org.gradle.api.artifacts.repositories.MavenArtifactRepository.reposiliteAuth() { + isAllowInsecureProtocol = true + credentials { + username = project.findProperty("reposilite.user") as String? + ?: System.getenv("REPOSILITE_USER") + password = project.findProperty("reposilite.token") as String? + ?: System.getenv("REPOSILITE_TOKEN") + } + authentication { + create("basic") + } + } + maven { + name = "ReposiliteReleases" + url = uri("http://repo.mastersmp.net/releases") + reposiliteAuth() + } + maven { + name = "ReposiliteSnapshots" + url = uri("http://repo.mastersmp.net/snapshots") + reposiliteAuth() + } + } +} + +val publishingSnapshot = gradle.startParameter.taskNames.any { + it == "publishSnapshot" || it.endsWith(":publishSnapshot") +} + +tasks.named("publishMavenPublicationToReposiliteReleasesRepository").configure { + onlyIf { !publishingSnapshot } +} + +tasks.named("publishMavenPublicationToReposiliteSnapshotsRepository").configure { + onlyIf { publishingSnapshot } +} + +tasks.named("publishAllPublicationsToReposiliteReleasesRepository").configure { + onlyIf { !publishingSnapshot } +} + +tasks.named("publishAllPublicationsToReposiliteSnapshotsRepository").configure { + onlyIf { publishingSnapshot } +} + +tasks.named("publish").configure { + group = "publishing" + description = "Publish fat jar to MasterSMP Reposilite releases" + dependsOn(tasks.shadowJar) +} + +tasks.register("publishSnapshot") { + group = "publishing" + description = "Publish fat jar to MasterSMP Reposilite snapshots" + dependsOn(tasks.shadowJar, "publishMavenPublicationToReposiliteSnapshotsRepository") +} + +tasks.named("publishToMavenLocal").configure { + dependsOn(tasks.shadowJar) +} + +tasks.register("printVersion") { + doLast { + println(version) + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..5cf7545d --- /dev/null +++ b/gradle.properties @@ -0,0 +1,6 @@ +version=2.6.1 +group=de.rapha149.signgui + +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000..b50af500 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,12 @@ +[versions] +paperweight-userdev = "2.0.0-beta.21" +shadow = "9.6.0" +folia-api = "1.21.11-R0.1-SNAPSHOT" + +[libraries] +paperweight-userdev = { group = "io.papermc.paperweight", name = "paperweight-userdev", version.ref = "paperweight-userdev" } +folia-api = { group = "dev.folia", name = "folia-api", version.ref = "folia-api" } + +[plugins] +shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } +paperweight-userdev = { id = "io.papermc.paperweight.userdev", version.ref = "paperweight-userdev" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..1b33c55b Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..a351597e --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..61460882 --- /dev/null +++ b/gradlew @@ -0,0 +1,245 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" \ No newline at end of file diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 12a15565..00000000 --- a/pom.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - 4.0.0 - - de.rapha149.signgui - signgui-parent - pom - 2.5.4 - - - api - wrapper - 1_8_R1 - 1_8_R2 - 1_8_R3 - 1_9_R1 - 1_9_R2 - 1_10_R1 - 1_11_R1 - 1_12_R1 - 1_13_R1 - 1_13_R2 - 1_14_R1 - 1_15_R1 - 1_16_R1 - 1_16_R2 - 1_16_R3 - 1_17_R1 - 1_18_R1 - 1_18_R2 - 1_19_R1 - 1_19_R2 - 1_19_R3 - 1_20_R1 - 1_20_R2 - 1_20_R3 - 1_20_R4 - Mojang1_20_R4 - 1_21_R1 - Mojang1_21_R1 - 1_21_R2 - Mojang1_21_R2 - 1_21_R3 - Mojang1_21_R3 - 1_21_R4 - Mojang1_21_R4 - 1_21_R5 - Mojang1_21_R5 - - - - UTF-8 - - - - - nms-repo - https://repo.codemc.org/repository/nms/ - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - - - - - - - - org.apache.maven.plugins - maven-source-plugin - 3.3.0 - - - attach-sources - - jar - - - - - - - diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..d730f954 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,49 @@ +rootProject.name = "SignGUI" + +pluginManagement { + includeBuild("build-logic") + repositories { + maven("https://plugins.gradle.org/m2/") + gradlePluginPortal() + mavenCentral() + maven("https://repo.papermc.io/repository/maven-public/") + } + plugins { + id("io.papermc.paperweight.userdev") version "2.0.0-beta.21" + id("com.gradleup.shadow") version "9.6.0" + } +} + +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" +} + +include(":wrapper") +include(":api") + +val spigotBuckets = listOf( + "1_8_R1", "1_8_R2", "1_8_R3", + "1_9_R1", "1_9_R2", + "1_10_R1", + "1_11_R1", + "1_12_R1", + "1_13_R1", "1_13_R2", + "1_14_R1", + "1_15_R1", + "1_16_R1", "1_16_R2", "1_16_R3", + "1_17_R1", + "1_18_R1", "1_18_R2", + "1_19_R1", "1_19_R2", "1_19_R3", + "1_20_R1", "1_20_R2", "1_20_R3", "1_20_R4", + "1_21_R1", "1_21_R2", "1_21_R3", "1_21_R4", "1_21_R5", "1_21_R6", "1_21_R7", +) + +val mojangBuckets = listOf( + "Mojang1_20_R4", + "Mojang1_21_R1", "Mojang1_21_R2", "Mojang1_21_R3", "Mojang1_21_R4", "Mojang1_21_R5", + "Mojang1_21_R6", "Mojang1_21_R7", + "Mojang26_1", "Mojang26_2", +) + +spigotBuckets.forEach { include(":$it") } +mojangBuckets.forEach { include(":$it") } diff --git a/Mojang1_21_R3/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R3.java b/shared-mojang-26/src/main/java/de/rapha149/signgui/version/MojangWrapperShared.java similarity index 94% rename from Mojang1_21_R3/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R3.java rename to shared-mojang-26/src/main/java/de/rapha149/signgui/version/MojangWrapperShared.java index 77ba30ca..5766b4d8 100644 --- a/Mojang1_21_R3/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R3.java +++ b/shared-mojang-26/src/main/java/de/rapha149/signgui/version/MojangWrapperShared.java @@ -25,10 +25,9 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; -public class MojangWrapper1_21_R3 implements VersionWrapper { +public class MojangWrapperShared implements VersionWrapper { @Override public Material getDefaultType() { @@ -136,27 +135,27 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } @Override public void displayNewLines(Player player, SignEditor signEditor, String[] textLines, Object[] adventureLines) { - SignBlockEntity sign = (SignBlockEntity)signEditor.getSign(); + SignBlockEntity sign = (SignBlockEntity) signEditor.getSign(); SignText newSignText = sign.getText(true); Component[] lines = createLines(textLines, adventureLines); - for(int i = 0; i < textLines.length; ++i) + for (int i = 0; i < textLines.length; ++i) newSignText = newSignText.setMessage(i, lines[i]); sign.setText(newSignText, true); - ServerPlayer p = ((CraftPlayer)player).getHandle(); + ServerPlayer p = ((CraftPlayer) player).getHandle(); ServerGamePacketListenerImpl conn = p.connection; sign.setLevel(p.level()); conn.send(sign.getUpdatePacket()); sign.setLevel(null); - conn.send(new ClientboundOpenSignEditorPacket((BlockPos)signEditor.getBlockPosition(), true)); + conn.send(new ClientboundOpenSignEditorPacket((BlockPos) signEditor.getBlockPosition(), true)); } @Override diff --git a/Mojang1_21_R2/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R2.java b/shared-mojang-modern/src/main/java/de/rapha149/signgui/version/MojangWrapperShared.java similarity index 97% rename from Mojang1_21_R2/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R2.java rename to shared-mojang-modern/src/main/java/de/rapha149/signgui/version/MojangWrapperShared.java index eb55b5d1..a6859b67 100644 --- a/Mojang1_21_R2/src/main/java/de/rapha149/signgui/version/MojangWrapper1_21_R2.java +++ b/shared-mojang-modern/src/main/java/de/rapha149/signgui/version/MojangWrapperShared.java @@ -25,10 +25,9 @@ import java.util.Arrays; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; -public class MojangWrapper1_21_R2 implements VersionWrapper { +public class MojangWrapperShared implements VersionWrapper { @Override public Material getDefaultType() { @@ -136,7 +135,7 @@ protected void decode(ChannelHandlerContext chc, Packet packet, List }; if (schedule) - SCHEDULER.schedule(runnable, 200, TimeUnit.MILLISECONDS); + scheduleReopen(player, loc, runnable); else runnable.run(); } diff --git a/wrapper/pom.xml b/wrapper/pom.xml deleted file mode 100644 index 9d031d23..00000000 --- a/wrapper/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - 4.0.0 - - - signgui-parent - de.rapha149.signgui - 2.5.4 - - - signgui-wrapper - - - true - - - - - org.spigotmc - spigot - 1.17-R0.1-SNAPSHOT - provided - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.2.0 - - 8 - - - - attach-javadocs - - jar - - - - - - - diff --git a/wrapper/src/main/java/de/rapha149/signgui/version/VersionWrapper.java b/wrapper/src/main/java/de/rapha149/signgui/version/VersionWrapper.java index 16a3607d..8e2a9a6d 100644 --- a/wrapper/src/main/java/de/rapha149/signgui/version/VersionWrapper.java +++ b/wrapper/src/main/java/de/rapha149/signgui/version/VersionWrapper.java @@ -1,14 +1,13 @@ package de.rapha149.signgui.version; import de.rapha149.signgui.SignEditor; +import de.rapha149.signgui.SignGUIBridge; import org.bukkit.DyeColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Player; import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; import java.util.function.BiConsumer; /** @@ -16,8 +15,6 @@ */ public interface VersionWrapper { - ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(0); - /** * @return The default type for the sign. Different between some versions. */ @@ -68,4 +65,12 @@ default Location getDefaultLocation(Player player) { Location loc = player.getEyeLocation(); return loc.clone().add(loc.getDirection().multiply(-3)); } + + /** + * Schedules a reopen after closing a previous SignGUI at the same position. + * Uses Folia/Paper entity schedulers when the API has registered one (~4 ticks ≈ 200ms). + */ + default void scheduleReopen(Player player, Location location, Runnable runnable) { + SignGUIBridge.runLater(player, location, runnable, 4L); + } }