diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..4701c19 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,43 @@ +name: Test Gradle build script + +on: + push: + branches: [ "ver/*", "dev/*", "feat/**/*" ] + paths: + - "*.kt" + - "*.kts" + - "*.toml" + - "gradle-wrapper.*" + workflow_dispatch: + +jobs: + check: + name: Test Gradle build script + strategy: + matrix: + jdk: [21] + java: ['zulu'] + os: [ubuntu-22.04] + + if: "!contains(github.event.commits[0].message, '[CheckSkip]')" + runs-on: ${{ matrix.os }} + steps: + - name: Checkout action + uses: actions/checkout@v3 + + - name: Validate Gradle Wrapper + uses: gradle/wrapper-validation-action@v1 + + - name: Set up JDK ${{ matrix.java }} ${{ matrix.jdk }} + uses: actions/setup-java@v3 + with: + distribution: ${{ matrix.java }} + java-version: ${{ matrix.jdk }} + cache: 'gradle' + + - name: Configure Git + run: | + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" && git config --global user.name "github-actions[bot]" + + - name: Run Gradle + run: ./gradlew --stacktrace diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e340f0f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,102 @@ +name: Release Volt + +on: + push: + branches: [ "ver/*", "dev/*", "feat/**/*" ] + paths: + - "**.patch" + workflow_dispatch: + +env: + ORG_NAME: PlazmaMC + MC_VERSION: 1.20.4 + +jobs: + release: + name: Release Volt + strategy: + matrix: + base_jdk: [17] + os: [ubuntu-22.04] + + if: "!startsWith(github.event.commits[0].message, '[CI-Skip]')" + runs-on: ${{ matrix.os }} + steps: + - name: Setup Variables + id: setup + env: + BRANCH: ${{ github.ref_name }} + run: echo "branch=${BRANCH##*/}" >> $GITHUB_OUTPUT + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Validate Gradle Wrapper + uses: gradle/wrapper-validation-action@v1 + + - name: Set up GraalVM ${{ matrix.base_jdk }} + uses: graalvm/setup-graalvm@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + java-version: ${{ matrix.base_jdk }} + version: latest + cache: 'gradle' + + - name: Configure Git + run: git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" && git config --global user.name "github-actions[bot]" + + - name: Apply Patches + run: ./gradlew applyPatches --stacktrace + + - name: Build + run: ./gradlew build --stacktrace + + - name: Create Reobf Jar + run: ./gradlew createReobfPaperclipJar --stacktrace + + - name: Create Mojmap Jar + run: ./gradlew createMojmapPaperclipJar --stacktrace + + - name: Publish Packages + if: startsWith(github.ref_name, 'ver/') || startsWith(github.ref_name, 'dev/') + run: | + export GITHUB_USERNAME=${{ env.ORG_NAME }} + export GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} + ./gradlew publish --stacktrace + + - name: Get Release Number + if: startsWith(github.ref_name, 'ver/') + run: echo "RELEASE=$(git ls-remote --tags origin | grep "build/${{ env.MC_VERSION }}" | wc -l)" >> $GITHUB_ENV + + - name: Release Artifacts + if: startsWith(github.ref_name, 'ver/') + uses: softprops/action-gh-release@v0.1.15 + with: + name: "Build #${{ env.RELEASE }} for ${{ env.MC_VERSION }}" + tag_name: build/${{ env.MC_VERSION }}/${{ env.RELEASE }} + target_commitish: ${{ github.ref_name }} + generate_release_notes: true + fail_on_unmatched_files: true + files: build/libs/*.jar + + - name: Release Artifacts (Latest/Stable) + if: startsWith(github.ref_name, 'ver/') + uses: softprops/action-gh-release@v0.1.15 + with: + name: "Build #${{ env.RELEASE }} for ${{ env.MC_VERSION }}" + tag_name: build/${{ env.MC_VERSION }}/latest + target_commitish: ${{ github.ref_name }} + generate_release_notes: true + fail_on_unmatched_files: true + files: build/libs/*.jar + + - name: Release Artifacts (Latest/Development) + if: startsWith(github.ref_name, 'dev/') + uses: softprops/action-gh-release@v0.1.15 + with: + name: "Development Build for ${{ env.MC_VERSION }}" + tag_name: build/${{ env.MC_VERSION }}/latest + target_commitish: ${{ github.ref_name }} + generate_release_notes: true + fail_on_unmatched_files: true + files: build/libs/*.jar diff --git a/.github/workflows/upstream.yml b/.github/workflows/upstream.yml new file mode 100644 index 0000000..796507f --- /dev/null +++ b/.github/workflows/upstream.yml @@ -0,0 +1,43 @@ +name: Always Up To Date +on: + workflow_dispatch: + schedule: + - cron: "*/20 * * * *" +jobs: + upstream: + name: Update Upstream + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Validate Gradle Wrapper + uses: gradle/wrapper-validation-action@v1 + + - name: Setup JDK + uses: actions/setup-java@v4 + with: + distribution: zulu + java-version: 21 + + - name: Determine if update is required + id: check + run: echo "needs=$(./gradlew -q checkNeedsUpdate)" >> $GITHUB_OUTPUT + + - name: Configure Git + if: steps.check.outputs.needs == 'true' + run: git config --global user.email "action@github.com" && git config --global user.name "Github Action" + + - name: Update upstream + if: steps.check.outputs.needs == 'true' + run: ./gradlew updateUpstream + + - name: Commit changes + if: steps.check.outputs.needs == 'true' + run: git add . && printf "Updated Upstream (Plazma)\n\nUpstream has released updates that appear to apply and compile correctly\n\n$(cat compare.txt)" | git commit -F - + + - name: Push changes + if: steps.check.outputs.needs == 'true' + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..086664a --- /dev/null +++ b/.gitignore @@ -0,0 +1,61 @@ +# JVM crash related +core.* +hs_err_pid* + +# Intellij +.idea/ +*.iml +*.ipr +*.iws +out/ + +# Eclipse +.classpath +.project +.settings/ + +# netbeans +nbproject/ +nbactions.xml + +# Gradle +!gradle-wrapper.jar +.gradle/ +build/ +*/build/ +run/ +javadoc/ + +# we use maven! +build.xml + +# Maven +log/ +target/ +dependency-reduced-pom.xml + +# various other potential build files +bin/ +dist/ +manifest.mf + +# Mac +.DS_Store/ +.DS_Store + +# vim +.*.sw[a-p] + +# Linux temp files +*~ + +# Paperweight +libs/ +build-data/ +*-API +*-MojangAPI +*-Server +paper-api-generator +compare.txt +*.patch +!patches/**/* diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..6c40a95 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,23 @@ +The MIT License (MIT) +===================== + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the “Software”), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..423c266 --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +
+ +# Thunderbolt + +### A Server platform with features too experimental to implement into Plazma + +[![Discord](https://img.shields.io/discord/1083716853928558652?style=for-the-badge&logo=discord&logoColor=ffffff&label=DISCORD&color=5865F2)](https://discord.gg/MmfC52K8A8) +[![License](https://img.shields.io/github/license/PlazmaMC/Thunderbolt?style=for-the-badge&logo=github&logoColor=ffffff)](LICENSE.md) +[![Stargazers](https://img.shields.io/github/stars/PlazmaMC/Thunderbolt?label=stars&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9bxSIVh1YQcYhQnSyIiuimVShChVArtOpgcukXNGlIUlwcBdeCgx+LVQcXZ10dXAVB8APE0clJ0UVK/F9SaBHjwXE/3t173L0D/PUyU82OMUDVLCOViAuZ7KrQ9YogwujDEGYkZupzopiE5/i6h4+vdzGe5X3uz9Gj5EwG+ATiWaYbFvEG8dSmpXPeJ46woqQQnxOPGnRB4keuyy6/cS447OeZESOdmieOEAuFNpbbmBUNlXiSOKqoGuX7My4rnLc4q+Uqa96TvzCU01aWuU5zEAksYgkiBMioooQyLMRo1UgxkaL9uId/wPGL5JLJVQIjxwIqUCE5fvA/+N2tmZ8Yd5NCcaDzxbY/hoGuXaBRs+3vY9tunACBZ+BKa/krdWD6k/RaS4seAb3bwMV1S5P3gMsdoP9JlwzJkQI0/fk88H5G35QFwrdA95rbW3Mfpw9AmrpK3gAHh8BIgbLXPd4dbO/t3zPN/n4Ax9dyyerighsAAAAGYktHRAAAAAAAAPlDu38AAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfmCBMVNjtc7/hFAAABIElEQVQ4y62SzS5DURSFv6smXkAUCRU0UdKYGNTPyCsYYOYFGGi8Ao9QM0PxCh6CgQ4qfiLpBFEjdKCfySaXtDch1uScs9Ze62TvcyAD6o66zV+gjqpvalsd61XXl5GxBySx3/3t7UPqi1pTD9VXdaRbbZIyDQLTwBSwBqzGGaABnAInwCXQSJLk/tO4orb8jra6nwo/CC6NlrqMOq421Y5aVSfUXJe2cqFVo7b5NdwIuVaf1IWM2cyrD+qdOvlTLERIS53pYi6FdqMWet2wGP1tdNE2Q1vK+gfDsdbDlFfzwV3Ems8KmAXegcd4hSvgVq0Bz6GV0ob+HgF1YAA4Cn4LWA9tLusHnscTHavFFF8MrqOeZQVU1HKGXlYr/Cc+AKuOI2h/Jrf7AAAAAElFTkSuQmCC&style=for-the-badge&color=green)](https://github.com/PlazmaMC/Thunderbolt/stargazers) + +[![Upstream Status](https://img.shields.io/github/actions/workflow/status/PlazmaMC/Thunderbolt/upstream.yml?label=upstream&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAGD0lEQVR4nO2dW4hVVRiAl5OjCFoMlpYx2WXMXjShi5FFTxFhhmFlQxlRU0kEXQiJorKIMoIiIoJegiiK8pKWZBTUg0ZpaHYhslBL8TKVTWWO00x98XP%2BicNhzt5rnb3P2WvtWd%2FjzDl7r%2FX%2F6%2FrfjjGRSCQSiUQikUgkEolEIpGIJwDHAHOA24CngTXA18Bu4BDwN3AUOAh8D3wOrAOeBLqBWUB70f0ICuBE4E7gXaCP7PwBrARuAqYU3T8vAdqB64EPgSGaxz%2F6joUyu8xoBzgOWAbsofXs0ndPNKMNoA24EThA8ezTPWZ0zAjgIt1IfWMbMM%2BUfJ1f3uQ1Po894rnSnZyAU3WEhcInwGmmDMi0BnozCGMA2KT3ADlKXgycAnQAY4HxwAnA6fouWc%2BfBzYCgxne%2BwtwgQkZ4Fq9KLlyBHgDWARMyPD%2BDr2QvamXNlf%2BAuabENGOu47AvcD9wOQmtOck4FG9NbsgfbjBhARwneNm26eCn9CCtk0EHtdZ5qKE%2BSEdM12WndVifiignbKPvOfQzsPA%2BSaA006vw%2Fq6pOD2jgHucRgw0rfpxkeAccBWBzPAHOMJMrIdBs4q4yNqArbhG2Ca8QxgBrDTov0yW8YaD9d9m013O3C88RRgmoUS%2Fm3FYcHVafKVhfB%2FAk42ngOcCfyc0I9txieApZYb7mwTCMBc4M8R%2BiGz%2FHLjC8CxlhebHhMYVDZmcXEO8wOwwPgEcJ%2BF8FebgAGmAp3GU%2FPyjxZLj5%2Fn5tBRH24aDxTdztICfGBhzp1UdDtLiYR3WJz7Hyy6naUFuCNF%2BGJ7n1p0O0uLRp8l8bYpIcAkYAXwKfAl8EzLg700pETCApPoNiUD6KpjppCTYFczXjimzt%2FPThH%2BULVHS00VfhmvGhO%2BeOvqsTc3JWgw7AagXx3i7wBnVf2%2FJ0UBn%2BnnZgLr9RniUfoYOM%2BUT%2Fj5KUGFP5IN5Dexj%2BhnniKZF9WWIt%2BppT8kJWAv%2FHyUoCM%2FyW8rgl2V0oiXU6KaPzLlFH42JejmKiM0CRHsfrIx6HscJo0LP7MSXCIFGkWU3GbKK%2FzGlaAZKM1mnSm%2F8BtTAnBGnc0zL%2BTZM8zoEH7DSpibU2rQiJu48RAqUXPNTBLZ4xT71AQleCt8AXid5vOacSFHJfgu%2FLYWHT4O17MuNFMJXgu%2FKqBMEjOy8Kve%2BNNMNO4mmQxK8F74wwBbEvoxoCmzafGtC1KUsMU0SgNKCEb4AnBZnVkwoIJ9KaW%2FK%2FQ59ZQgz77UZMFBCUEJfxjgSg09qY7iu1D%2FlxbzenPVc%2BapryD%2FcBYLJQQp%2FJoNuVOOpTXu17Q9YnadMMfO3G%2F9CZbO%2Fy2mZQJYYhF80FZE%2FORbmuS8T3OwvLzhZkX9IUmsyfySyMhIMLFF9MfSOl%2BPZAV4zCL6w9tw%2B6ChEnicFnywvuh2lhbgEdJZXHQ7SwkwXW03aXluQUd7eIlmTko0Rxp3G5%2BQ4hZVR9M%2B7cQsExhUyqWlccCrQk%2BaH3ywTr22YC5nwDkWgQnCLcYngFcTGisJbzON51AZRDJ709jqXVCBhTtvp4%2B5wTWVGr%2B1DKnxb0YDOywav8vHmUDFYPYddiw3PgK8YtmBXp9GEHCu5i%2FbsNnbUmZ6bk5Kbq5N9b%2FX2T%2Baf5t7LDdcNBrQv0zJaqS8l2ZF2vJ%2BERmUamCzOecPc8SnWZsIcIVjlax%2B4IlWJPNpoaaH9WhsixjbrjIBOjBcS5X1quUx95OSerQeaqBIrAj%2FahMiOhNclqPqTq%2FUHOTJGUf7Yr2Z267z1ch3FpmQ0T1B3HWNMqT1O18AbtdylV06osdrpn6Hlqu8RG6nwLOSoZOxXOX%2B4MtV1tiHRIihsNn7044rWlzV95LFg5p%2BOs6UFY2X8bF88RfBHDNziru5xqLKSiuQi%2BNdvqdLNQU9pSzT34JpNbu1VKU%2F9vyioJLEvVArr2SNUE5b4zdoRd%2FoRqyjjClaHV3O7r%2FnIHQJGV%2BrNe1i6IjjzGjXn6DqVlPFWq3ftkM9b0f10nZIfQ3bNX9ZkshvlVhN75wmkUgkEolEIpFIJBKJRCIRM5r5D9WH9bFOGhrhAAAAAElFTkSuQmCC&style=flat-square)](https://github.com/PlazmaMC/Thunderbolt/actions/workflows/upstream.yml) +[![Forks](https://img.shields.io/github/forks/PlazmaMC/Thunderbolt?label=forks&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9bxSIVh1YQcYhQnSyIiuimVShChVArtOpgcukXNGlIUlwcBdeCgx+LVQcXZ10dXAVB8APE0clJ0UVK/F9SaBHjwXE/3t173L0D/PUyU82OMUDVLCOViAuZ7KrQ9YogwujDEGYkZupzopiE5/i6h4+vdzGe5X3uz9Gj5EwG+ATiWaYbFvEG8dSmpXPeJ46woqQQnxOPGnRB4keuyy6/cS447OeZESOdmieOEAuFNpbbmBUNlXiSOKqoGuX7My4rnLc4q+Uqa96TvzCU01aWuU5zEAksYgkiBMioooQyLMRo1UgxkaL9uId/wPGL5JLJVQIjxwIqUCE5fvA/+N2tmZ8Yd5NCcaDzxbY/hoGuXaBRs+3vY9tunACBZ+BKa/krdWD6k/RaS4seAb3bwMV1S5P3gMsdoP9JlwzJkQI0/fk88H5G35QFwrdA95rbW3Mfpw9AmrpK3gAHh8BIgbLXPd4dbO/t3zPN/n4Ax9dyyerighsAAAAGYktHRAAAAAAAAPlDu38AAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfmCBMVNCYN3/YeAAAA/UlEQVQ4y7WTQUoDQRBFf01czlJcxUyOINGjjAvFHMFzZGdygOwDwTtk6UZcqLlAxCAuMigug89FamIzdAIN+qGhq/6v6qrqbumvAJwBj8AHMAQs4DJgBHy65jSW4Bl4AaZsUAbcufumrnmquSzIcSzpTtLA7XbA1fuBa9qxCob8YgUUAdcFqoC/iSXIgLELOhG+49w4nM+2BTP7ljR3M4/MufbNzYxdN1E0Sm2ialZnsVIllZKOJF24eyLpXdKtmS1S3sYMmO3THOwJziUdbrbkZvaVcnILeAh6vweylAQ9D7z2BXCS0sJS0lrSpdtrSW+pn6sPLIFX4Er/hR9C0wl1FTBzNwAAAABJRU5ErkJggg==&style=flat-square&color=green)](https://github.com/PlazmaMC/Volt/forks) +[![Watchers](https://img.shields.io/github/watchers/PlazmaMC/Thunderbolt?label=watchers&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9bxSIVh1YQcYhQnSyIiuimVShChVArtOpgcukXNGlIUlwcBdeCgx+LVQcXZ10dXAVB8APE0clJ0UVK/F9SaBHjwXE/3t173L0D/PUyU82OMUDVLCOViAuZ7KrQ9YogwujDEGYkZupzopiE5/i6h4+vdzGe5X3uz9Gj5EwG+ATiWaYbFvEG8dSmpXPeJ46woqQQnxOPGnRB4keuyy6/cS447OeZESOdmieOEAuFNpbbmBUNlXiSOKqoGuX7My4rnLc4q+Uqa96TvzCU01aWuU5zEAksYgkiBMioooQyLMRo1UgxkaL9uId/wPGL5JLJVQIjxwIqUCE5fvA/+N2tmZ8Yd5NCcaDzxbY/hoGuXaBRs+3vY9tunACBZ+BKa/krdWD6k/RaS4seAb3bwMV1S5P3gMsdoP9JlwzJkQI0/fk88H5G35QFwrdA95rbW3Mfpw9AmrpK3gAHh8BIgbLXPd4dbO/t3zPN/n4Ax9dyyerighsAAAAGYktHRAAAAAAAAPlDu38AAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfmCBMVNw4TRw0nAAAA3UlEQVQ4y83SP04CURAG8I0lewHOwAFUaiwkdmAlp8CL4FHopfIvtOIJWE3opIBK489mQPKy6xYWOskkL9/MN/PNzMuyf2fIcYkZVuGzwPI68gle8Yl7jMIfAntBp4o8wAeecFgSP8I8cgZp8DwC12j8oLCBCd7R34ItbHCzT8ZZSC7QTYrcYo1WhjGWaCbdCt+2SGLN4IwPfnu07QjrkhG6oWKB0+TMd7sRAuzHYuqWmO8tsVd1xjmOS8htPEfORVWHTmweHnEVPg2sqPxIicxhFFjhLd7D2q/8J/YFHSJt9VSqQ08AAAAASUVORK5CYII=&style=flat-square&color=green)](https://github.com/PlazmaMC/Thunderbolt/watchers) + +
+ +[main]: https://github.com/PlazmaMC/Thunderbolt + +> [!WARNING] +Thunderbolt는 Plazma에 추가하기에 매우 불안정하고 게임 플레이에 크게 영향을 미치는 패치가 포함된 프로젝트입니다! +기존 월드가 손상되거나, 일부 플러그인이 작동하지 않을 수 있으며, 매 업데이트마다 서버의 안정 상태가 크게 달라질 수 있습니다! +Thunberbolt는 공개 서버에서 사용하기 매우 부적합하고, Plazma에 패치를 추가하기 전 실험용으로 사용되는 프로젝트입니다! 사용에 주의해주세요!
+Thunderbolt is a project that includes patches that are very unstable to add to Plazma and greatly affect gameplay! +Existing worlds may be damaged, some plugins may not work, and the server's stable status can vary greatly with each update! +Thunderbolt is very unfit for public servers, and it is an experimental project before adding patches to Plazma! Please be careful! + +> [!IMPORTANT] +This is the FO experimental branch of Thunderbolt 1.20.6. If you are curious about other versions of Thunderbolt, please check **[main branch][main]**.
+이곳은 Thunderbolt 1.20.6의 FO 실험 분기입니다. Thunderbolt의 다른 버전이 궁금하다면 **[main 분기][main]** 를 확인해 주세요. + +## ⬇️ Downloads +> [!NOTE] +If you don't know about Mojmap or Bundler, download **Mojmap Paperclip**
+Mojmap 또는 Bundler에 대해 잘 알지 못한다면, **Mojmap Paperclip**을 사용하세요 + +[paperReobf]: https://github.com/PlazmaMC/Thunderbolt/releases/download/build/fo/latest/thunderbolt-paperclip-1.20.6-R0.1-SNAPSHOT-reobf.jar +[paperMojmap]: https://github.com/PlazmaMC/Thunderbolt/releases/download/build/fo/latest/thunderbolt-paperclip-1.20.6-R0.1-SNAPSHOT-mojmap.jar +[bundlerReobf]: https://github.com/PlazmaMC/Thunderbolt/releases/download/build/fo/latest/thunderbolt-bundler-1.20.6-R0.1-SNAPSHOT-reobf.jar +[bundlerMojmap]: https://github.com/PlazmaMC/Thunderbolt/releases/download/build/fo/latest/thunderbolt-bundler-1.20.6-R0.1-SNAPSHOT-mojmap.jar + +| **Reobf Paperclip (Default)** | Mojmap Paperclip | Reobf Bundler | Mojmap Bundler | +|:-----------------------------:|:-----------------------:|:------------------------:|:-------------------------:| +| [Download][paperReobf] | [Download][paperMojmap] | [Download][bundlerReobf] | [Download][bundlerMojmap] | diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..f861843 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,233 @@ +import io.papermc.paperweight.util.* +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.gradle.api.tasks.testing.logging.TestLogEvent + +plugins { + java + `kotlin-dsl` + `maven-publish` + id("com.github.johnrengelman.shadow") version "8.1.1" apply false + id("io.papermc.paperweight.patcher") version "1.6.3" +} + +repositories { + mavenCentral() + maven("https://papermc.io/repo/repository/maven-public/") { + content { + onlyForConfigurations(configurations.paperclip.name) + } + } +} + +val jdkVersion = property("jdkVersion").toString().toInt() +val projectName = property("projectName").toString() +val projectRepo = property("projectRepo").toString() +val upstreamRef = property("plazmaRef").toString() +val upstreamCommitValue = property("plazmaCommit").toString() + +kotlin.jvmToolchain(jdkVersion) + +dependencies { + remapper("net.fabricmc:tiny-remapper:0.8.10:fat") + decompiler("org.vineflower:vineflower:1.10.1") + paperclip("io.papermc:paperclip:3.0.3") +} + +allprojects { + apply(plugin = "java") + apply(plugin = "maven-publish") + + java.toolchain.languageVersion.set(JavaLanguageVersion.of(jdkVersion)) + + publishing { + repositories { + maven { + name = "githubPackage" + url = uri("https://maven.pkg.github.com/$projectRepo") // Volt - Change this + + credentials { + username = System.getenv("GITHUB_USERNAME") + password = System.getenv("GITHUB_TOKEN") + } + } + + publications.register("gpr") { + from(components["java"]) + } + } + } +} + +subprojects { + tasks { + withType().configureEach { + options.compilerArgs.addAll(listOf("--add-modules=jdk.incubator.vector", "-Xmaxwarns", "1")) + options.encoding = Charsets.UTF_8.name() + options.release = jdkVersion + } + + withType { + options.encoding = Charsets.UTF_8.name() + } + + withType { + filteringCharset = Charsets.UTF_8.name() + } + + withType { + testLogging { + showStackTraces = true + exceptionFormat = TestExceptionFormat.FULL + events(TestLogEvent.STANDARD_OUT) + } + } + } + + repositories { + mavenCentral() + maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") + maven("https://papermc.io/repo/repository/maven-public/") + maven("https://jitpack.io") + } +} + +paperweight { + serverProject = project(":${projectName.lowercase()}-server") + + remapRepo = "https://papermc.io/repo/repository/maven-public/" + decompileRepo = "https://papermc.io/repo/repository/maven-public/" + + useStandardUpstream("plazma") { + url = github("PlazmaMC", "PlazmaBukkit") + ref = providers.gradleProperty("plazmaCommit") + + withStandardPatcher { + baseName("Plazma") + + apiPatchDir = layout.projectDirectory.dir("patches/api") + apiOutputDir = layout.projectDirectory.dir("$projectName-API") + + serverPatchDir = layout.projectDirectory.dir("patches/server") + serverOutputDir = layout.projectDirectory.dir("$projectName-Server") + } + + patchTasks.register("mojangApi") { + isBareDirectory = true + upstreamDirPath = "Plazma-MojangAPI" + patchDir = layout.projectDirectory.dir("patches/mojang-api") + outputDir = layout.projectDirectory.dir("$projectName-MojangAPI") + } + + patchTasks.register("generatedApi") { + isBareDirectory = true + upstreamDirPath = "paper-api-generator/generated" + patchDir = layout.projectDirectory.dir("patches/generated-api") + outputDir = layout.projectDirectory.dir("paper-api-generator/generated") + } + + patchTasks.register("versionCatalogs") { + isBareDirectory = true + upstreamDirPath = "libs" + patchDir = layout.projectDirectory.dir("patches/version-catalog") + outputDir = layout.projectDirectory.dir("libs") + } + } +} + +tasks { + applyPatches { + dependsOn("applyVersionCatalogsPatches") + dependsOn("applyGeneratedApiPatches") + } + + rebuildPatches { + dependsOn("rebuildVersionCatalogsPatches") + dependsOn("rebuildGeneratedApiPatches") + } + + generateDevelopmentBundle { + apiCoordinates = "$group:$projectName-api" + mojangApiCoordinates = "$group:$projectName-mojangapi" + libraryRepositories.set( + listOf( + "https://repo.maven.apache.org/maven2/", + "https://maven.pkg.github.com/$projectRepo", + "https://papermc.io/repo/repository/maven-public/" + ) + ) + } + + register("checkNeedsUpdate") { + var latest: String = "" + + doFirst { + val commit = layout.cache.resolve("commit.json") + download.get().download("https://api.github.com/repos/PlazmaMC/PlazmaBukkit/commits/$upstreamRef", commit) + latest = gson.fromJson(commit)["sha"].asString + } + + doLast { + println(latest != property("plazmaCommit")) + } + } + + register("updateUpstream") { + val tempDir = layout.cacheDir("updateUpstream") + val file = "gradle.properties" + val builder = StringBuilder() + + doFirst { + val commit = layout.cache.resolve("commit.json") + download.get().download("https://api.github.com/repos/PlazmaMC/PlazmaBukkit/commits/$upstreamRef", commit) + val latestCommit = gson.fromJson(commit)["sha"].asString + + val compare = layout.cache.resolve("compare.json") + download.get().download("https://api.github.com/repos/PlazmaMC/PlazmaBukkit/compare/$upstreamCommitValue...$upstreamRef", compare) + gson.fromJson(compare)["commits"].asJsonArray.forEach { + builder.append("PlazmaMC/PlazmaBukkit@${it.asJsonObject["sha"].asString.subSequence(0, 7)}: ${it.asJsonObject["commit"].asJsonObject["message"].asString.split("\n")[0]}\n") + } + + copy { + from(file) + into(tempDir) + filter { + it.replace("plazmaCommit = .*".toRegex(), "plazmaCommit = $latestCommit") + } + } + + project.setProperty("plazmaCommit", latestCommit) + } + + doLast { + copy { + from(tempDir.file("gradle.properties")) + into(project.file(file).parent) + } + project.file("compare.txt").writeText(builder.toString()) + } + + finalizedBy(applyPatches) + } + + clean { + doLast { + projectDir.resolve(".gradle/caches").deleteRecursively() + listOf("$projectName-API", "$projectName-MojangAPI", "$projectName-Server", "paper-api-generator", "run").forEach { + projectDir.resolve(it).deleteRecursively() + } + + // remove dev environment files + listOf("0001-fixup.patch", "compare.txt").forEach { + projectDir.resolve(it).delete() + } + } + } +} + +publishing { + publications.create("devBundle") { + artifact(tasks.generateDevelopmentBundle) { + artifactId = "dev-bundle" + } + } +} diff --git a/fxapi b/fxapi new file mode 100755 index 0000000..d25667b --- /dev/null +++ b/fxapi @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# FixupAPI + +PS1="$" + +cd *-API + +git add . +git commit -m "fixup" +git format-patch -1 +mv 0001-fixup.patch ../ + +cd ../ diff --git a/fxsrv b/fxsrv new file mode 100755 index 0000000..85f8772 --- /dev/null +++ b/fxsrv @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# FixupServer + +PS1="$" + +cd *-Server + +git add . +git commit -m "fixup" +git format-patch -1 +mv 0001-fixup.patch ../ + +cd ../ diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..b194212 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,23 @@ +org.gradle.deamon = true +org.gradle.caching = true +org.gradle.parallel = true +org.gradle.vfs.watch = false +org.gradle.jvmargs = -Xmx4G -Dfile.encoding=UTF-8 -Dgraal.CompilerConfiguration=community -Dgraal.UsePriorityInlining=true -Dgraal.Vectorization=true -Dgraal.OptDuplication=true -Dgraal.SpeculativeGuardMovement=true -Dgraal.WriteableCodeCache=true + +# Volt - for Debugging +paper.runMemoryGb = 8 +paper.runDisableWatchdog = true + +# Volt - Change below values +group = org.plazmamc.thunderbolt +projectName = Thunderbolt +projectRepo = PlazmaMC/Thunderbolt + +# Volt - You must change below values when you upgrade the Minecraft. +version = 1.20.6-R0.1-SNAPSHOT +mcVersion = 1.20.6 +plazmaRef = dev/1.20.6 +jdkVersion = 21 + +# Volt - Use ./gradlew updateUpstream to update this value +plazmaCommit = 069250da5981752ace0db45a789ccd38b64475cc diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e644113 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 0000000..b82aa23 --- /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-8.7-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..1aa94a4 --- /dev/null +++ b/gradlew @@ -0,0 +1,249 @@ +#!/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##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && 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 + if ! command -v java >/dev/null 2>&1 + then + 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 +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=SC2039,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=SC2039,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, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +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" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..7101f8e --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/patches/api/0001-Configuration-API.patch b/patches/api/0001-Configuration-API.patch new file mode 100644 index 0000000..df295ad --- /dev/null +++ b/patches/api/0001-Configuration-API.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaKR93 +Date: Sun, 12 Jun 2022 10:57:51 -0500 +Subject: [PATCH] Configuration API + + +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index f1b39968788f90ffc785b9dd434b2a3671553a14..90eb3884f5283fa6c52ff2267570c466b2fdd463 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -2276,6 +2276,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + } + // Plazma end + ++ // Thunderbolt - Configuration API ++ @NotNull ++ public org.bukkit.configuration.file.YamlConfiguration getThunderboltConfig() { ++ throw new UnsupportedOperationException("Not implemented yet."); ++ } ++ // Thunderbolt end ++ + /** + * Sends the component to the player + * diff --git a/patches/server/0001-Rebranding.patch b/patches/server/0001-Rebranding.patch new file mode 100644 index 0000000..ba74e03 --- /dev/null +++ b/patches/server/0001-Rebranding.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaKR93 +Date: Thu, 9 May 2024 12:47:04 +0900 +Subject: [PATCH] Rebranding + + +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index d2215f5293c568b4ae525f4a63996bac6edf787b..fcd474949f1a5b4108d635e659bfe0a0ba551583 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -117,15 +117,19 @@ public class Main { + // \033[38;2;236;61;151m┃\033[38;2;236;61;157m \033[38;2;237;62;163m┃\033[38;2;237;62;169m \033[38;2;238;62;175m \033[38;2;238;63;181m \033[38;2;239;63;187m \033[38;2;239;63;193m \033[38;2;239;64;200m┃\033[38;2;240;64;206m \033[38;2;240;64;212m┗\033[38;2;241;65;218m━\033[38;2;241;65;224m━\033[38;2;242;65;230m━\033[38;2;242;66;236m━\033[38;2;242;66;242m┓\033[38;2;237;66;243m┃\033[38;2;232;67;243m \033[38;2;227;67;244m┃\033[38;2;221;67;244m \033[38;2;216;68;244m \033[38;2;211;68;245m┃\033[38;2;205;69;245m \033[38;2;200;69;246m┃\033[38;2;195;69;246m┏\033[38;2;189;70;246m┛\033[38;2;184;70;247m \033[38;2;179;70;247m \033[38;2;173;71;247m┗\033[38;2;168;71;248m━\033[38;2;163;72;248m━\033[38;2;157;72;249m┓\033[38;2;152;72;249m┃\033[38;2;147;73;249m \033[38;2;141;73;250m┃\033[38;2;136;74;250m \033[38;2;131;74;250m┗\033[38;2;125;74;251m━\033[38;2;120;75;251m┛\033[38;2;115;75;251m \033[38;2;109;76;252m┃\033[38;2;104;76;252m \033[38;2;99;77;252m┃\033[38;2;94;77;253m┃\033[38;2;88;77;253m \033[38;2;83;78;253m┃\033[38;2;78;79;254m \033[38;2;79;85;254m \033[38;2;79;91;254m┃\033[38;2;80;97;255m \033[38;2;80;103;255m┃ + // \033[38;2;236;61;151m┗\033[38;2;236;61;157m━\033[38;2;237;62;163m┛\033[38;2;237;62;169m \033[38;2;238;62;175m \033[38;2;238;63;181m \033[38;2;239;63;187m \033[38;2;239;63;193m \033[38;2;239;64;200m┗\033[38;2;240;64;206m━\033[38;2;240;64;212m━\033[38;2;241;65;218m━\033[38;2;241;65;224m━\033[38;2;242;65;230m━\033[38;2;242;66;236m━\033[38;2;242;66;242m┛\033[38;2;237;66;243m┗\033[38;2;232;67;243m━\033[38;2;227;67;244m┛\033[38;2;221;67;244m \033[38;2;216;68;244m \033[38;2;211;68;245m┗\033[38;2;205;69;245m━\033[38;2;200;69;246m┛\033[38;2;195;69;246m┗\033[38;2;189;70;246m━\033[38;2;184;70;247m━\033[38;2;179;70;247m━\033[38;2;173;71;247m━\033[38;2;168;71;248m━\033[38;2;163;72;248m━\033[38;2;157;72;249m┛\033[38;2;152;72;249m┗\033[38;2;147;73;249m━\033[38;2;141;73;250m┛\033[38;2;136;74;250m \033[38;2;131;74;250m \033[38;2;125;74;251m \033[38;2;120;75;251m \033[38;2;115;75;251m \033[38;2;109;76;252m┗\033[38;2;104;76;252m━\033[38;2;99;77;252m┛\033[38;2;94;77;253m┗\033[38;2;88;77;253m━\033[38;2;83;78;253m┛\033[38;2;78;79;254m \033[38;2;79;85;254m \033[38;2;79;91;254m┗\033[38;2;80;97;255m━\033[38;2;80;103;255m┛\033[0m + // """); ++ // Thunderbolt start - Branding + System.out.println(""" +- +- \033[38;2;215;23;133m█\033[38;2;212;24;134m█\033[38;2;209;26;134m█\033[38;2;205;27;135m█\033[38;2;202;28;136m█\033[38;2;199;30;136m█\033[38;2;196;31;137m╗\033[38;2;193;33;138m \033[38;2;190;34;138m█\033[38;2;186;35;139m█\033[38;2;183;37;140m╗\033[38;2;180;38;140m \033[38;2;177;39;141m \033[38;2;174;41;142m \033[38;2;170;42;142m \033[38;2;167;43;143m \033[38;2;164;45;144m \033[38;2;161;46;144m█\033[38;2;158;47;145m█\033[38;2;155;49;146m█\033[38;2;151;50;146m█\033[38;2;148;52;147m█\033[38;2;145;53;148m╗\033[38;2;142;54;148m \033[38;2;139;56;149m█\033[38;2;135;57;149m█\033[38;2;132;58;150m█\033[38;2;129;60;151m█\033[38;2;126;61;151m█\033[38;2;123;62;152m█\033[38;2;120;64;153m█\033[38;2;116;65;153m╗ \033[38;2;113;67;154m█\033[38;2;110;68;155m█\033[38;2;107;69;155m█\033[38;2;104;71;156m╗\033[38;2;101;72;157m \033[38;2;97;73;157m \033[38;2;94;75;158m \033[38;2;91;76;159m█\033[38;2;88;77;159m█\033[38;2;85;79;160m█\033[38;2;81;80;161m╗ \033[38;2;78;81;161m \033[38;2;75;83;162m█\033[38;2;72;84;163m█\033[38;2;69;86;163m█\033[38;2;66;87;164m█\033[38;2;62;88;165m█\033[38;2;59;90;165m╗\033[38;2;56;91;166m\s +- \033[38;2;215;23;133m█\033[38;2;212;24;134m█\033[38;2;209;26;134m╔\033[38;2;205;27;135m═\033[38;2;202;28;136m═\033[38;2;199;30;136m█\033[38;2;196;31;137m█\033[38;2;193;33;138m╗ \033[38;2;190;34;138m█\033[38;2;186;35;139m█\033[38;2;183;37;140m║\033[38;2;180;38;140m \033[38;2;177;39;141m \033[38;2;174;41;142m \033[38;2;170;42;142m \033[38;2;167;43;143m \033[38;2;164;45;144m█\033[38;2;161;46;144m█\033[38;2;158;47;145m╔\033[38;2;155;49;146m═\033[38;2;151;50;146m═\033[38;2;148;52;147m█\033[38;2;145;53;148m█\033[38;2;142;54;148m╗ \033[38;2;139;56;149m╚\033[38;2;135;57;149m═\033[38;2;132;58;150m═\033[38;2;129;60;151m█\033[38;2;126;61;151m█\033[38;2;123;62;152m█\033[38;2;120;64;153m╔\033[38;2;116;65;153m╝ \033[38;2;113;67;154m█\033[38;2;110;68;155m█\033[38;2;107;69;155m█\033[38;2;104;71;156m█\033[38;2;101;72;157m╗\033[38;2;97;73;157m \033[38;2;94;75;158m█\033[38;2;91;76;159m█\033[38;2;88;77;159m█\033[38;2;85;79;160m█\033[38;2;81;80;161m║ \033[38;2;78;81;161m█\033[38;2;75;83;162m█\033[38;2;72;84;163m╔\033[38;2;69;86;163m═\033[38;2;66;87;164m═\033[38;2;62;88;165m█\033[38;2;59;90;165m█\033[38;2;56;91;166m╗ +- \033[38;2;215;23;133m█\033[38;2;212;24;134m█\033[38;2;209;26;134m█\033[38;2;205;27;135m█\033[38;2;202;28;136m█\033[38;2;199;30;136m█\033[38;2;196;31;137m╔\033[38;2;193;33;138m╝ \033[38;2;190;34;138m█\033[38;2;186;35;139m█\033[38;2;183;37;140m║\033[38;2;180;38;140m \033[38;2;177;39;141m \033[38;2;174;41;142m \033[38;2;170;42;142m \033[38;2;167;43;143m \033[38;2;164;45;144m█\033[38;2;161;46;144m█\033[38;2;158;47;145m█\033[38;2;155;49;146m█\033[38;2;151;50;146m█\033[38;2;148;52;147m█\033[38;2;145;53;148m█\033[38;2;142;54;148m║ \033[38;2;139;56;149m \033[38;2;135;57;149m \033[38;2;132;58;150m█\033[38;2;129;60;151m█\033[38;2;126;61;151m█\033[38;2;123;62;152m╔\033[38;2;120;64;153m╝\033[38;2;116;65;153m \033[38;2;113;67;154m█\033[38;2;110;68;155m█\033[38;2;107;69;155m╔\033[38;2;104;71;156m█\033[38;2;101;72;157m█\033[38;2;97;73;157m█\033[38;2;94;75;158m█\033[38;2;91;76;159m╔\033[38;2;88;77;159m█\033[38;2;85;79;160m█\033[38;2;81;80;161m║ \033[38;2;78;81;161m█\033[38;2;75;83;162m█\033[38;2;72;84;163m█\033[38;2;69;86;163m█\033[38;2;66;87;164m█\033[38;2;62;88;165m█\033[38;2;59;90;165m█\033[38;2;56;91;166m║ +- \033[38;2;215;23;133m█\033[38;2;212;24;134m█\033[38;2;209;26;134m╔\033[38;2;205;27;135m═\033[38;2;202;28;136m═\033[38;2;199;30;136m═\033[38;2;196;31;137m╝\033[38;2;193;33;138m \033[38;2;190;34;138m█\033[38;2;186;35;139m█\033[38;2;183;37;140m║\033[38;2;180;38;140m \033[38;2;177;39;141m \033[38;2;174;41;142m \033[38;2;170;42;142m \033[38;2;167;43;143m \033[38;2;164;45;144m█\033[38;2;161;46;144m█\033[38;2;158;47;145m╔\033[38;2;155;49;146m═\033[38;2;151;50;146m═\033[38;2;148;52;147m█\033[38;2;145;53;148m█\033[38;2;142;54;148m║ \033[38;2;139;56;149m \033[38;2;135;57;149m█\033[38;2;132;58;150m█\033[38;2;129;60;151m█\033[38;2;126;61;151m╔\033[38;2;123;62;152m╝\033[38;2;120;64;153m \033[38;2;116;65;153m \033[38;2;113;67;154m█\033[38;2;110;68;155m█\033[38;2;107;69;155m║\033[38;2;104;71;156m╚\033[38;2;101;72;157m█\033[38;2;97;73;157m█\033[38;2;94;75;158m╔\033[38;2;91;76;159m╝\033[38;2;88;77;159m█\033[38;2;85;79;160m█\033[38;2;81;80;161m║ \033[38;2;78;81;161m█\033[38;2;75;83;162m█\033[38;2;72;84;163m╔\033[38;2;69;86;163m═\033[38;2;66;87;164m═\033[38;2;62;88;165m█\033[38;2;59;90;165m█\033[38;2;56;91;166m║ +- \033[38;2;215;23;133m█\033[38;2;212;24;134m█\033[38;2;209;26;134m║\033[38;2;205;27;135m \033[38;2;202;28;136m \033[38;2;199;30;136m \033[38;2;196;31;137m \033[38;2;193;33;138m \033[38;2;190;34;138m█\033[38;2;186;35;139m█\033[38;2;183;37;140m█\033[38;2;180;38;140m█\033[38;2;177;39;141m█\033[38;2;174;41;142m█\033[38;2;170;42;142m█\033[38;2;167;43;143m╗ \033[38;2;164;45;144m█\033[38;2;161;46;144m█\033[38;2;158;47;145m║\033[38;2;155;49;146m \033[38;2;151;50;146m \033[38;2;148;52;147m█\033[38;2;145;53;148m█\033[38;2;142;54;148m║ \033[38;2;139;56;149m█\033[38;2;135;57;149m█\033[38;2;132;58;150m█\033[38;2;129;60;151m█\033[38;2;126;61;151m█\033[38;2;123;62;152m█\033[38;2;120;64;153m█\033[38;2;116;65;153m╗ \033[38;2;113;67;154m█\033[38;2;110;68;155m█\033[38;2;107;69;155m║\033[38;2;104;71;156m \033[38;2;101;72;157m╚\033[38;2;97;73;157m═\033[38;2;94;75;158m╝\033[38;2;91;76;159m \033[38;2;88;77;159m█\033[38;2;85;79;160m█\033[38;2;81;80;161m║ \033[38;2;78;81;161m█\033[38;2;75;83;162m█\033[38;2;72;84;163m║\033[38;2;69;86;163m \033[38;2;66;87;164m \033[38;2;62;88;165m█\033[38;2;59;90;165m█\033[38;2;56;91;166m║ +- \033[38;2;215;23;133m╚\033[38;2;212;24;134m═\033[38;2;209;26;134m╝\033[38;2;205;27;135m \033[38;2;202;28;136m \033[38;2;199;30;136m \033[38;2;196;31;137m \033[38;2;193;33;138m \033[38;2;190;34;138m╚\033[38;2;186;35;139m═\033[38;2;183;37;140m═\033[38;2;180;38;140m═\033[38;2;177;39;141m═\033[38;2;174;41;142m═\033[38;2;170;42;142m═\033[38;2;167;43;143m╝ \033[38;2;164;45;144m╚\033[38;2;161;46;144m═\033[38;2;158;47;145m╝\033[38;2;155;49;146m \033[38;2;151;50;146m \033[38;2;148;52;147m╚\033[38;2;145;53;148m═\033[38;2;142;54;148m╝ \033[38;2;139;56;149m╚\033[38;2;135;57;149m═\033[38;2;132;58;150m═\033[38;2;129;60;151m═\033[38;2;126;61;151m═\033[38;2;123;62;152m═\033[38;2;120;64;153m═\033[38;2;116;65;153m╝ \033[38;2;113;67;154m╚\033[38;2;110;68;155m═\033[38;2;107;69;155m╝\033[38;2;104;71;156m \033[38;2;101;72;157m \033[38;2;97;73;157m \033[38;2;94;75;158m \033[38;2;91;76;159m \033[38;2;88;77;159m╚\033[38;2;85;79;160m═\033[38;2;81;80;161m╝ \033[38;2;78;81;161m╚\033[38;2;75;83;162m═\033[38;2;72;84;163m╝\033[38;2;69;86;163m \033[38;2;66;87;164m \033[38;2;62;88;165m╚\033[38;2;59;90;165m═\033[38;2;56;91;166m╝\033[0m +- """); ++ \033[95m ++ ********** ** ** ** ** ** \s ++ /////**/// /** /** /** /** /** \s ++ /** /** ** ** ******* /** ***** ****** /** ****** /** ****** ++ /** /****** /** /** //**///** ****** **///** //**//* /****** **////** /** ///**/\s ++ /** /**///** /** /** /** /** **///** /******* /** / /**///** /** /** /** /** \s ++ /** /** /** /** /** /** /** /** /** /**//// /** /** /** /** /** /** /** \s ++ /** /** /** //****** *** /** //****** //****** /*** /****** //****** *** //**\s ++ // // // ////// /// // ////// ////// /// ///// ////// /// // \s\033[0m ++ """); ++ // Thunderbolt end - Branding + // Plazma end + // Plazma start - Warn on startup + if (!org.plazmamc.plazma.Options.NO_WARN) { +diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +index 2612df0680800e8c4644599b1885230778c812b7..c87390df0aa77d7d1399096a62c109aab6736d82 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +@@ -11,16 +11,18 @@ import org.bukkit.Bukkit; + public final class Versioning { + // Plazma start - Rebrand; Branding utils + private static String version = "Unknown-Version"; +- public static final String BRANDING = "Plazma"; ++ // Thunderbolt start - Rebranding ++ public static final String BRANDING = "Thunderbolt"; + public static final String BRAND_L = BRANDING.toLowerCase(Locale.ROOT); + public static final String BRAND_U = BRANDING.toUpperCase(Locale.ROOT); +- public static final String REPOSITORY = "PlazmaMC/PlazmaBukkit"; +- public static final String DOWNLOAD = "https://plazmamc.org/downloads"; ++ public static final String REPOSITORY = "PlazmaMC/Thunderbolt"; ++ public static final String DOWNLOAD = "https://github.com/PlazmaMC/Thunderbolt/releases"; // TODO: Move to docs ++ // Thunderbolt end - Rebranding + public static final String DOCUMENT = "https://docs.plazmamc.org/plazma/administration/getting-started"; + public static final String STEP_UP = "https://docs.plazmamc.org/plazma/administration/getting-started/next-step"; + public static final boolean DEVELOPMENT = true; // Plazma - Development build + static { +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.plazmamc.plazma/plazma-api/pom.properties"); ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.plazmamc.thunderbolt/thunderbolt-api/pom.properties"); // Thunderbolt - Rebranding + Properties properties = new Properties(); + + if (stream != null) { diff --git a/patches/server/0002-Configurable-Thunderbolt.patch b/patches/server/0002-Configurable-Thunderbolt.patch new file mode 100644 index 0000000..bb6a8ae --- /dev/null +++ b/patches/server/0002-Configurable-Thunderbolt.patch @@ -0,0 +1,749 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alpha +Date: Sun, 25 Feb 2024 19:13:15 +0900 +Subject: [PATCH] Configurable Thunderbolt + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 4635d67ed906886f533b6d5911d99a163810ea11..b179aaad657396771213c8b02e29ee6f61faedb0 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -318,6 +318,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig, minecraftserver.registryAccess(), iworlddataserver.getGameRules())), + spigotConfig -> minecraftserver.plazmaConfigurations.createWorldConfig(org.plazmamc.plazma.configurations.PlazmaConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig, minecraftserver.registryAccess(), iworlddataserver.getGameRules())), ++ spigotConfig -> minecraftserver.thunderboltConfigurations.createWorldConfig(org.plazmamc.thunderbolt.configurations.ThunderboltConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig, minecraftserver.registryAccess(), iworlddataserver.getGameRules())), // Thunderbolt - Configurable Thunderbolt + executor + ); + // Plazma end - Configurable Plazma +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 47fcbff8a0b7feedbc700b6c3cf44d3a02a60246..b7e58a6b11e648999a97add335cc13e27dcf6861 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -174,6 +174,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return this.plazmaConfig; + } + // Plazma end - Configurable Plazma ++ // Thunderbolt start - Configurable Thunderbolt ++ private final org.plazmamc.thunderbolt.configurations.WorldConfigurations thunderboltConfig; ++ public org.plazmamc.thunderbolt.configurations.WorldConfigurations thunderboltConfig() { ++ return this.thunderboltConfig; ++ } ++ // Thunderbolt end - Configurable Thunderbolt + + public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + public final org.purpurmc.purpur.PurpurWorldConfig purpurConfig; // Purpur +@@ -279,12 +285,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + org.bukkit.World.Environment env, + java.util.function.Function paperWorldConfigCreator, + java.util.function.Function plazmaWorldConfigurationCreator, ++ java.util.function.Function thunderboltWorldConfigurationCreator, // Thunderbolt - Configurable Thunderbolt + java.util.concurrent.Executor executor + ) { + // Plazma end - Configurable Plazma + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot + this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config + this.plazmaConfig = plazmaWorldConfigurationCreator.apply(this.spigotConfig); // Plazma - Configurable Plazma ++ this.thunderboltConfig = thunderboltWorldConfigurationCreator.apply(this.spigotConfig); // Thunderbolt - Configurable Thunderbolt + this.purpurConfig = new org.purpurmc.purpur.PurpurWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), env); // Purpur + this.playerBreedingCooldowns = this.getNewBreedingCooldownCache(); // Purpur + this.generator = gen; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index d53be3e57e97cf9806b04f6d6bdd6a3a9fdb299b..4f5290801f9bdd3f9c300bd445f089a63e1ad998 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1069,6 +1069,7 @@ public final class CraftServer implements Server { + org.spigotmc.SpigotConfig.init((File) this.console.options.valueOf("spigot-settings")); // Spigot + this.console.paperConfigurations.reloadConfigs(this.console); + this.console.plazmaConfigurations.reloadConfigs(this.console); // Plazma - Configurable Plazma ++ this.console.thunderboltConfigurations.reloadConfigs(this.console); // Thunderbolt - Configurable Thunderbolt + org.purpurmc.purpur.PurpurConfig.init((File) console.options.valueOf("purpur-settings")); // Purpur + for (ServerLevel world : this.console.getAllLevels()) { + // world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty +@@ -3134,6 +3135,13 @@ public final class CraftServer implements Server { + } + // Plazma end - Configurable Plazma + ++ // Thunderbolt start - Configurable Thunderbolt ++ @Override @org.jetbrains.annotations.NotNull ++ public YamlConfiguration getThunderboltConfig() { ++ return CraftServer.this.console.thunderboltConfigurations.createLegacyObject(CraftServer.this.console); ++ } ++ // Thunderbolt end - Configurable Thunderbolt ++ + @Override + public void restart() { + org.spigotmc.RestartCommand.restart(); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 40fd40da9a7fc2b12035b99960e7f38c78eb2a5e..c6f35002b8ef7bbd0e490b7bcaae4c6e5d3832aa 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -198,6 +198,14 @@ public class Main { + .defaultsTo(new File(org.plazmamc.plazma.configurations.PlazmaConfigurations.CONFIG_DIR)) + .describedAs("Configuration Directory"); + // Plazma end - Configurable Plazma ++ ++ // Thunderbolt start - Configurable Thunderbolt ++ acceptsAll(asList("thunderbolt-dir", "thunderbolt-settings-directory"), "Directory for Thunderbolt settings") ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File(org.plazmamc.thunderbolt.configurations.ThunderboltConfigurations.CONFIG_DIR)) ++ .describedAs("Configuration Directory"); ++ // Thunderbolt end - Configurable Thunderbolt + } + }; + +diff --git a/src/main/java/org/plazmamc/thunderbolt/commands/Commands.java b/src/main/java/org/plazmamc/thunderbolt/commands/Commands.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a943c5ffd470f7919855a434900504cce477160b +--- /dev/null ++++ b/src/main/java/org/plazmamc/thunderbolt/commands/Commands.java +@@ -0,0 +1,22 @@ ++package org.plazmamc.thunderbolt.commands; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.command.Command; ++import org.checkerframework.framework.qual.DefaultQualifier; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.HashMap; ++import java.util.Map; ++ ++@DefaultQualifier(NotNull.class) ++public class Commands { ++ ++ private static final Map COMMANDS = new HashMap<>() {{ ++ put("thunderbolt", new org.plazmamc.thunderbolt.commands.thunderbolt.ThunderboltCommand("thunderbolt")); ++ }}; ++ ++ public static void register(final MinecraftServer server) { ++ COMMANDS.forEach((name, command) -> server.server.getCommandMap().register(name, "Thunderbolt", command)); ++ } ++ ++} +diff --git a/src/main/java/org/plazmamc/thunderbolt/commands/ThunderboltSubCommand.java b/src/main/java/org/plazmamc/thunderbolt/commands/ThunderboltSubCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bf5fa777a4d1187e7f86708d892a24f2a4f738ef +--- /dev/null ++++ b/src/main/java/org/plazmamc/thunderbolt/commands/ThunderboltSubCommand.java +@@ -0,0 +1,19 @@ ++package org.plazmamc.thunderbolt.commands; ++ ++import org.bukkit.command.CommandSender; ++import org.checkerframework.framework.qual.DefaultQualifier; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.Collections; ++import java.util.List; ++ ++@DefaultQualifier(NotNull.class) ++public interface ThunderboltSubCommand { ++ ++ boolean execute(final CommandSender sender, final String subCommand, final String[] args); ++ ++ default List tabComplete(final CommandSender sender, final String subCommand, final String[] args) { ++ return Collections.emptyList(); ++ } ++ ++} +diff --git a/src/main/java/org/plazmamc/thunderbolt/commands/thunderbolt/ThunderboltCommand.java b/src/main/java/org/plazmamc/thunderbolt/commands/thunderbolt/ThunderboltCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d366faa50f12ecd0cd9167c6a746ef715ddcb303 +--- /dev/null ++++ b/src/main/java/org/plazmamc/thunderbolt/commands/thunderbolt/ThunderboltCommand.java +@@ -0,0 +1,118 @@ ++package org.plazmamc.thunderbolt.commands.thunderbolt; ++ ++import io.papermc.paper.command.CommandUtil; ++import net.kyori.adventure.text.format.NamedTextColor; ++import it.unimi.dsi.fastutil.Pair; ++import net.minecraft.Util; ++import org.bukkit.Bukkit; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.bukkit.permissions.Permission; ++import org.bukkit.permissions.PermissionDefault; ++import org.checkerframework.framework.qual.DefaultQualifier; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.plazmamc.thunderbolt.commands.thunderbolt.subcommand.ReloadCommand; ++import org.plazmamc.thunderbolt.commands.thunderbolt.subcommand.VersionCommand; ++ ++import java.util.*; ++import java.util.stream.Collectors; ++ ++import static net.kyori.adventure.text.Component.text; ++ ++@DefaultQualifier(NotNull.class) ++public class ThunderboltCommand extends Command { ++ ++ private static final String PERMISSION = "bukkit.command.thunderbolt"; ++ ++ private static final Map SUB_COMMANDS = Util.make(() -> { ++ final Map, org.plazmamc.thunderbolt.commands.ThunderboltSubCommand> commands = new HashMap<>() {{ ++ put(Set.of("reload"), new ReloadCommand()); ++ put(Set.of("version"), new VersionCommand()); ++ }}; ++ ++ return commands.entrySet().stream() ++ .flatMap(entry -> entry.getKey().stream().map(key -> Map.entry(key, entry.getValue()))) ++ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); ++ }); ++ ++ private static final Map ALIASES = Util.make(() -> { ++ final Map> aliases = new HashMap<>() {{ ++ put("reload", Set.of("rl")); ++ put("version", Set.of("ver")); ++ }}; ++ ++ return aliases.entrySet().stream() ++ .flatMap(entry -> entry.getValue().stream().map(val -> Map.entry(val, entry.getKey()))) ++ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); ++ }); ++ ++ public ThunderboltCommand(final String name) { ++ super(name); ++ ++ final List permissions = new ArrayList<>() {{ ++ add(PERMISSION); ++ addAll(SUB_COMMANDS.keySet().stream().map(key -> PERMISSION + "." + key).toList()); ++ }}; ++ ++ this.description = "Thunderbolt related commands"; ++ this.usageMessage = String.format("/thunderbolt [%s]", String.join("|", SUB_COMMANDS.keySet())); ++ this.setPermission(String.join(";", permissions)); ++ ++ permissions.forEach(perm -> Bukkit.getServer().getPluginManager().addPermission(new Permission(perm, PermissionDefault.OP))); ++ } ++ ++ @Override ++ public boolean execute(final CommandSender sender, final String commandLabel, final String[] args) { ++ if (!testPermission(sender)) return true; ++ ++ if (args.length == 0) { ++ sender.sendMessage(text("Usage: " + this.usageMessage, NamedTextColor.RED)); ++ return false; ++ } ++ ++ final @Nullable Pair subCommand = resolveSubCommand(args[0]); ++ ++ if (subCommand == null) { ++ sender.sendMessage(text("Usage: " + this.usageMessage, NamedTextColor.RED)); ++ return false; ++ } ++ ++ if (!testPermission(sender, subCommand.first())) return true; ++ ++ return subCommand.second().execute(sender, subCommand.first(), Arrays.copyOfRange(args, 1, args.length)); ++ } ++ ++ @Override ++ public List tabComplete(final CommandSender sender, final String aliases, final String[] args) throws IllegalArgumentException { ++ if (args.length <= 1) return CommandUtil.getListMatchingLast(sender, args, SUB_COMMANDS.keySet()); ++ ++ final @Nullable Pair subCommand = resolveSubCommand(args[0]); ++ ++ if (subCommand != null) return subCommand.second().tabComplete(sender, subCommand.first(), Arrays.copyOfRange(args, 1, args.length)); ++ return Collections.emptyList(); ++ } ++ ++ private static boolean testPermission(final CommandSender sender, final String permission) { ++ if (sender.hasPermission(PERMISSION + "." + permission) || sender.hasPermission(PERMISSION)) return true; ++ sender.sendMessage(Bukkit.permissionMessage()); ++ return false; ++ } ++ ++ private static @Nullable Pair resolveSubCommand(String label) { ++ label = label.toLowerCase(); ++ @Nullable org.plazmamc.thunderbolt.commands.ThunderboltSubCommand subCommand = SUB_COMMANDS.get(label); ++ ++ if (subCommand == null) { ++ final @Nullable String command = ALIASES.get(label); ++ if (command != null) { ++ label = command; ++ subCommand = SUB_COMMANDS.get(label); ++ } ++ } ++ ++ if (subCommand != null) return Pair.of(label, subCommand); ++ return null; ++ } ++ ++} +diff --git a/src/main/java/org/plazmamc/thunderbolt/commands/thunderbolt/subcommand/ReloadCommand.java b/src/main/java/org/plazmamc/thunderbolt/commands/thunderbolt/subcommand/ReloadCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9afee425a7cf37bc0a61097b3f9833ffe0c881c9 +--- /dev/null ++++ b/src/main/java/org/plazmamc/thunderbolt/commands/thunderbolt/subcommand/ReloadCommand.java +@@ -0,0 +1,34 @@ ++package org.plazmamc.thunderbolt.commands.thunderbolt.subcommand; ++ ++import net.kyori.adventure.text.format.NamedTextColor; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.bukkit.craftbukkit.CraftServer; ++import org.checkerframework.framework.qual.DefaultQualifier; ++import org.jetbrains.annotations.NotNull; ++import org.plazmamc.thunderbolt.commands.ThunderboltSubCommand; ++ ++import static net.kyori.adventure.text.Component.text; ++ ++@DefaultQualifier(NotNull.class) ++public class ReloadCommand implements ThunderboltSubCommand { ++ ++ @Override ++ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) { ++ reload(sender); ++ return true; ++ } ++ ++ private static void reload(final CommandSender sender) { ++ Command.broadcastCommandMessage(sender, text("Please note that this command is not supported and may cause issues.", NamedTextColor.RED)); ++ Command.broadcastCommandMessage(sender, text("If you encounter any issues please use the /stop command to restart your server.", NamedTextColor.RED)); ++ ++ MinecraftServer server = ((CraftServer) sender.getServer()).getServer(); ++ server.thunderboltConfigurations.reloadConfigs(server); ++ server.server.reloadCount++; ++ ++ Command.broadcastCommandMessage(sender, text("Successfully reloaded Thunderbolt configuration files.", NamedTextColor.GREEN)); ++ } ++ ++} +diff --git a/src/main/java/org/plazmamc/thunderbolt/commands/thunderbolt/subcommand/VersionCommand.java b/src/main/java/org/plazmamc/thunderbolt/commands/thunderbolt/subcommand/VersionCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b859430a39546cded05032110163d67671cd346e +--- /dev/null ++++ b/src/main/java/org/plazmamc/thunderbolt/commands/thunderbolt/subcommand/VersionCommand.java +@@ -0,0 +1,21 @@ ++package org.plazmamc.thunderbolt.commands.thunderbolt.subcommand; ++ ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.checkerframework.framework.qual.DefaultQualifier; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.plazmamc.thunderbolt.commands.ThunderboltSubCommand; ++ ++@DefaultQualifier(NotNull.class) ++public class VersionCommand implements ThunderboltSubCommand { ++ ++ @Override ++ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) { ++ final @Nullable Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version"); ++ if (ver != null) return ver.execute(sender, "thunderbolt", new String[0]); ++ return false; ++ } ++ ++} +diff --git a/src/main/java/org/plazmamc/thunderbolt/configurations/GlobalConfiguration.java b/src/main/java/org/plazmamc/thunderbolt/configurations/GlobalConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fbac06d6c70fd6250f16a6bdbea21873ff5e1d2a +--- /dev/null ++++ b/src/main/java/org/plazmamc/thunderbolt/configurations/GlobalConfiguration.java +@@ -0,0 +1,28 @@ ++package org.plazmamc.thunderbolt.configurations; ++ ++import io.papermc.paper.configuration.Configuration; ++import io.papermc.paper.configuration.ConfigurationPart; ++import org.jetbrains.annotations.NotNull; ++import org.spongepowered.configurate.objectmapping.meta.Setting; ++import org.spongepowered.configurate.objectmapping.meta.PostProcess; ++ ++import static org.plazmamc.plazma.configurations.PlazmaConfigurations.optimize; ++ ++@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal", "FieldMayBeFinal", "InnerClassMayBeStatic"}) ++public class GlobalConfiguration extends ConfigurationPart { ++ ++ private static GlobalConfiguration INSTANCE; ++ static final int VERSION = 1; ++ ++ public static GlobalConfiguration get() { ++ return INSTANCE; ++ } ++ ++ static void set(final @NotNull GlobalConfiguration instance) { ++ GlobalConfiguration.INSTANCE = instance; ++ } ++ ++ @Setting(Configuration.VERSION_FIELD) ++ int version = VERSION; ++ ++} +diff --git a/src/main/java/org/plazmamc/thunderbolt/configurations/RemovedConfigurations.java b/src/main/java/org/plazmamc/thunderbolt/configurations/RemovedConfigurations.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1d4afff273484b08d340e7b8d80e031325a76945 +--- /dev/null ++++ b/src/main/java/org/plazmamc/thunderbolt/configurations/RemovedConfigurations.java +@@ -0,0 +1,13 @@ ++package org.plazmamc.thunderbolt.configurations; ++ ++import org.spongepowered.configurate.NodePath; ++ ++interface RemovedConfigurations { ++ ++ NodePath[] WORLD_PATHS = { ++ }; ++ ++ NodePath[] GLOBAL_PATHS = { ++ }; ++ ++} +diff --git a/src/main/java/org/plazmamc/thunderbolt/configurations/ThunderboltConfigurations.java b/src/main/java/org/plazmamc/thunderbolt/configurations/ThunderboltConfigurations.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2b6653148b6a3586373efffa7a74caf2dd5e560c +--- /dev/null ++++ b/src/main/java/org/plazmamc/thunderbolt/configurations/ThunderboltConfigurations.java +@@ -0,0 +1,209 @@ ++package org.plazmamc.thunderbolt.configurations; ++ ++import com.mojang.logging.LogUtils; ++import io.papermc.paper.configuration.ConfigurationPart; ++import io.papermc.paper.configuration.Configurations; ++import joptsimple.OptionSet; ++import net.minecraft.core.RegistryAccess; ++import net.minecraft.server.level.ServerLevel; ++import org.checkerframework.framework.qual.DefaultQualifier; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.VisibleForTesting; ++import org.slf4j.Logger; ++import org.spongepowered.configurate.ConfigurationOptions; ++import org.spongepowered.configurate.yaml.YamlConfigurationLoader; ++import org.spongepowered.configurate.ConfigurateException; ++import org.spongepowered.configurate.BasicConfigurationNode; ++import org.spongepowered.configurate.ConfigurationNode; ++import org.spongepowered.configurate.objectmapping.ObjectMapper; ++import org.spongepowered.configurate.NodePath; ++ ++import java.io.File; ++import java.util.function.Function; ++ ++import static io.leangen.geantyref.GenericTypeReflector.erase; ++ ++@DefaultQualifier(NotNull.class) ++public class ThunderboltConfigurations extends Configurations { ++ ++ public static final String CONFIG_DIR = "config"; ++ static final Logger LOGGER = LogUtils.getClassLogger(); ++ static final String GLOBAL_CONFIG_FILE_NAME = "thudnerbolt_global.yaml"; ++ static final String WORLD_DEFAULT_CONFIG_FILE_NAME = "thunderbolt_world_defaults.yaml"; ++ static final String WORLD_CONFIG_FILE_NAME = "thunderbolt.yaml"; ++ static boolean GLOBAL_LOADED = false; ++ ++ private static final String HEADER_START = """ ++ ### ENGLISH ### ++ Volt is a template project that helps you fork your Plazma easily. ++ This software is not suitable for use as a regular server. If you ++ are not a fork developer, and you just want to run a server, ++ please use Plazma. ++ ++ %s ++ ++ ### KOREAN ### ++ Volt는 Plazma를 쉽게 포크할 수 있도록 도와주는 템플릿 프로젝트입니다. ++ 이 소프트웨어는 일반 서버로 사용하기 적합하지 않습니다. 당신이 포크 ++ 개발자가 아니고, 단지 서버를 운영하고 싶다면, Plazma를 사용해 주십시오. ++ ++ %s ++ ++ GitHub: https://github.com/PlazmaMC/Volt ++ Development Guide: https://github.com/PlazmaMC/Volt/wiki ++ ++ Download Plazma: https://github.com/PlazmaMC/PlazmaBukkit?tab=readme-ov-file#️-downloads ++ Discord: https://plazmamc.org/discord ++ """; ++ ++ private static final String GLOBAL_HEADER = HEADER_START.formatted(""" ++ Below are several template values set in GlobalConfiguration.java. ++ Refer to the class for more information on how the configuration applies. ++ These are values that apply to the **entire server** regardless of ++ the world. However, you must take advantage of the system properties ++ in order for the server to be able to modify the values before ++ loading the configuration. See org.plazmamc.thunderbolt.Options class for ++ development of system properties. ++ """, """ ++ 아래에는 GlobalConfiguration.java에 설정된 여러 템플릿 값들이 있습니다. ++ 구성이 적용되는 여러 방법은 해당 클래스를 참고하세요. ++ 이 값들은 월드에 관계 없이 **서버 전체**에 적용되는 값들입니다. 다만, 서버가 구성을 ++ 로드하기 전의 값을 수정할 수 있게 만드려면, 시스템 속성을 이용해야 합니다. ++ 시스템 속성에 대한 개발은 org.plazmamc.thunderbolt.Options 클래스를 참고하세요. ++ """ ++ ); ++ ++ private static final String WORLD_DEFAULT_HEADER = HEADER_START.formatted(""" ++ Below are several template values that are set in WorldConfigurations.java. ++ Refer to the class for more information on how the configuration applies. ++ These are values that apply to the **entire game (world)** regardless ++ of the world. However, these world configurations can be set to ++ override values that apply only to that world through the ++ %WORLD_CONFIG_FILE_NAME% file in the world folder. ++ """, """ ++ 아래에는 WorldConfigurations.java에 설정된 여러 템플릿 값들이 있습니다. ++ 구성이 적용되는 여러 방법은 해당 클래스를 참고하세요. ++ 이 값들은 월드에 관계 없이 **게임(월드) 전체**에 적용되는 값들입니다. 다만, ++ 이러한 월드 구성은 월드 폴더 내에 있는 %WORLD_CONFIG_FILE_NAME% 파일을 통해 ++ 해당 월드에만 적용되는 덮어쓰기 값을 설정할 수 있습니다. ++ """ ++ ).replace("%WORLD_CONFIG_FILE_NAME%", WORLD_CONFIG_FILE_NAME); ++ ++ private static final Function WORLD_HEADER = map -> """ ++ ### ENGLISH ### ++ This file is a Volt configuration file for %s (%s) world only. ++ This file is empty in its initial state, but you can populate the ++ values set in the %s file to override them. ++ ++ ### KOREAN ### ++ 본 파일은 %s (%s) 월드 전용 Volt 구성 파일입니다. ++ 이 파일은 초기 상태에는 비어있지만, %s 파일에 설정된 값을 덮어쓰기 위해 값을 채워 ++ 넣을 수 있습니다. ++ """.formatted( ++ map.require(WORLD_NAME), map.require(WORLD_KEY), WORLD_CONFIG_FILE_NAME, ++ map.require(WORLD_NAME), map.require(WORLD_KEY), WORLD_CONFIG_FILE_NAME ++ ); ++ ++ public ThunderboltConfigurations(final OptionSet optionSet) { ++ super(((File) optionSet.valueOf("thunderbolt-settings-directory")).toPath()); ++ } ++ ++ @Override ++ protected Class globalConfigClass() { ++ return GlobalConfiguration.class; ++ } ++ ++ @Override ++ protected String globalConfigFileName() { ++ return GLOBAL_CONFIG_FILE_NAME; ++ } ++ ++ @Override ++ protected NodePath[] removedGlobalPaths() { ++ return RemovedConfigurations.GLOBAL_PATHS; ++ } ++ ++ @Override ++ protected GlobalConfiguration getGlobalConfiguration() { ++ return GlobalConfiguration.get(); ++ } ++ ++ @Override ++ protected int globalConfigVersion() { ++ return GlobalConfiguration.VERSION; ++ } ++ ++ @Override ++ protected Class worldConfigClass() { ++ return WorldConfigurations.class; ++ } ++ ++ @Override ++ protected String defaultWorldConfigFileName() { ++ return WORLD_DEFAULT_CONFIG_FILE_NAME; ++ } ++ ++ @Override ++ protected String worldConfigFileName() { ++ return WORLD_CONFIG_FILE_NAME; ++ } ++ ++ @Override ++ protected String worldDefaultHeader() { ++ return WORLD_DEFAULT_HEADER; ++ } ++ ++ @Override ++ protected NodePath[] removedWorldPaths() { ++ return RemovedConfigurations.WORLD_PATHS; ++ } ++ ++ @Override ++ protected WorldConfigurations getWorldConfiguration(ServerLevel level) { ++ throw new UnsupportedOperationException("TODO"); ++ } ++ ++ @Override ++ protected int worldConfigVersion() { ++ return WorldConfigurations.VERSION; ++ } ++ ++ @Override ++ protected String buildWorldHeader(ContextMap contextMap) { ++ return WORLD_HEADER.apply(contextMap); ++ } ++ ++ @Override ++ protected YamlConfigurationLoader.Builder createGlobalLoaderBuilder() { ++ return super.createGlobalLoaderBuilder() ++ .defaultOptions(ThunderboltConfigurations::defaultGlobalOptions); ++ } ++ ++ @Override ++ public GlobalConfiguration initializeGlobalConfiguration(final RegistryAccess registryAccess) throws ConfigurateException { ++ GlobalConfiguration configuration = super.initializeGlobalConfiguration(registryAccess); ++ GlobalConfiguration.set(configuration); ++ GLOBAL_LOADED = true; ++ return configuration; ++ } ++ ++ @Override ++ protected WorldConfigurations createWorldConfigInstance(ContextMap contextMap) { ++ return new WorldConfigurations(contextMap.require(WORLD_KEY)); ++ } ++ ++ private static ConfigurationOptions defaultGlobalOptions( ++ final ConfigurationOptions options ++ ) { ++ return options.header(GLOBAL_HEADER); ++ } ++ ++ @VisibleForTesting ++ static ConfigurationNode createForTesting() { ++ ObjectMapper.Factory factory = defaultGlobalFactoryBuilder(ObjectMapper.factoryBuilder()).build(); ++ ConfigurationOptions options = defaultGlobalOptions(defaultOptions(ConfigurationOptions.defaults())) ++ .serializers(builder -> builder.register(type -> ConfigurationPart.class.isAssignableFrom(erase(type)), factory.asTypeSerializer())); ++ return BasicConfigurationNode.root(options); ++ } ++ ++} +diff --git a/src/main/java/org/plazmamc/thunderbolt/configurations/WorldConfigurations.java b/src/main/java/org/plazmamc/thunderbolt/configurations/WorldConfigurations.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4a8bff4b6e42c3fa49758520e743dc65fe79e2cc +--- /dev/null ++++ b/src/main/java/org/plazmamc/thunderbolt/configurations/WorldConfigurations.java +@@ -0,0 +1,23 @@ ++package org.plazmamc.thunderbolt.configurations; ++ ++import io.papermc.paper.configuration.Configuration; ++import io.papermc.paper.configuration.ConfigurationPart; ++import org.jetbrains.annotations.NotNull; ++import net.minecraft.resources.ResourceLocation; ++import org.spongepowered.configurate.objectmapping.meta.PostProcess; ++import org.spongepowered.configurate.objectmapping.meta.Setting; ++ ++@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal", "FieldMayBeFinal", "InnerClassMayBeStatic"}) ++public class WorldConfigurations extends ConfigurationPart { ++ ++ static final int VERSION = 1; ++ ++ private transient final ResourceLocation worldKey; ++ public WorldConfigurations(final @NotNull ResourceLocation worldKey) { ++ this.worldKey = worldKey; ++ } ++ ++ @Setting(Configuration.VERSION_FIELD) ++ int version = VERSION; ++ ++} +diff --git a/src/test/java/org/bukkit/support/AbstractTestingBase.java b/src/test/java/org/bukkit/support/AbstractTestingBase.java +index 74af3501397bfd89d637ad5ce72bb8f2c2bbdc8a..93767e76b6ea52da8587f282dfe18774e9dad22f 100644 +--- a/src/test/java/org/bukkit/support/AbstractTestingBase.java ++++ b/src/test/java/org/bukkit/support/AbstractTestingBase.java +@@ -65,6 +65,7 @@ public abstract class AbstractTestingBase { + DummyServer.setup(); + io.papermc.paper.configuration.GlobalConfigTestingBase.setupGlobalConfigForTest(); // Paper + org.plazmamc.plazma.configurations.GlobalConfigurationTestingBase.setupGlobalConfigForTest(); // Plazma - Configurable Plazma ++ org.plazmamc.thunderbolt.configurations.GlobalConfigurationTestingBase.setupGlobalConfigurationForTesting(); // Thunderbolt - Configurable Thunderbolt + + CraftRegistry.setMinecraftRegistry(REGISTRY_CUSTOM); + +diff --git a/src/test/java/org/plazmamc/thunderbolt/configurations/GlobalConfigurationTestingBase.java b/src/test/java/org/plazmamc/thunderbolt/configurations/GlobalConfigurationTestingBase.java +new file mode 100644 +index 0000000000000000000000000000000000000000..682089f155c75b0c106c3516f053fde7787b400c +--- /dev/null ++++ b/src/test/java/org/plazmamc/thunderbolt/configurations/GlobalConfigurationTestingBase.java +@@ -0,0 +1,17 @@ ++package org.plazmamc.thunderbolt.configurations; ++ ++import org.spongepowered.configurate.ConfigurationNode; ++ ++public class GlobalConfigurationTestingBase { ++ ++ public static void setupGlobalConfigurationForTesting() { ++ if (GlobalConfiguration.get() != null) return; ++ ConfigurationNode node = ThunderboltConfigurations.createForTesting(); ++ try { ++ GlobalConfiguration.set(node.require(GlobalConfiguration.class)); ++ } catch (Exception e) { ++ throw new RuntimeException(e); ++ } ++ } ++ ++} diff --git a/patches/server/0003-Add-basic-configuration-parts.patch b/patches/server/0003-Add-basic-configuration-parts.patch new file mode 100644 index 0000000..3310950 --- /dev/null +++ b/patches/server/0003-Add-basic-configuration-parts.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaKR93 +Date: Fri, 10 May 2024 12:50:20 +0900 +Subject: [PATCH] Add basic configuration parts + + +diff --git a/src/main/java/org/plazmamc/thunderbolt/configurations/GlobalConfiguration.java b/src/main/java/org/plazmamc/thunderbolt/configurations/GlobalConfiguration.java +index fbac06d6c70fd6250f16a6bdbea21873ff5e1d2a..0b16bbf87a6c5e658e8182e423800acd16dfc7ca 100644 +--- a/src/main/java/org/plazmamc/thunderbolt/configurations/GlobalConfiguration.java ++++ b/src/main/java/org/plazmamc/thunderbolt/configurations/GlobalConfiguration.java +@@ -25,4 +25,20 @@ public class GlobalConfiguration extends ConfigurationPart { + @Setting(Configuration.VERSION_FIELD) + int version = VERSION; + ++ public NeedsReload needsReload; ++ public class NeedsReload extends ConfigurationPart { ++ ++ ++ @PostProcess ++ public void post() { ++ if (ThunderboltConfigurations.GLOBAL_LOADED) { ++ ThunderboltConfigurations.LOGGER.warn("Configuration settings that require a restart have been changed." ++ + "The settings will take effect at the next restart."); ++ return; ++ } ++ ++ } ++ ++ } ++ + } diff --git a/patches/server/0004-Implement-Noisium.patch b/patches/server/0004-Implement-Noisium.patch new file mode 100644 index 0000000..f580810 --- /dev/null +++ b/patches/server/0004-Implement-Noisium.patch @@ -0,0 +1,243 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AlphaKR93 +Date: Fri, 10 May 2024 11:31:37 +0900 +Subject: [PATCH] Implement Noisium + + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index a2a5aef769ee8bb638a5a9f3da9812fa4a85dda5..39960b9d4099cd22bd695a06355f0045a35049a1 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -19,8 +19,8 @@ public class LevelChunkSection { + public static final int SECTION_HEIGHT = 16; + public static final int SECTION_SIZE = 4096; + public static final int BIOME_CONTAINER_BITS = 2; +- short nonEmptyBlockCount; // Paper - package private +- private short tickingBlockCount; ++ public short nonEmptyBlockCount; // Paper - package private // Thunderbolt - Implement noisium; why? ++ public short tickingBlockCount; // Thunderbolt - AT + private short tickingFluidCount; + public final PalettedContainer states; + // CraftBukkit start - read/write +@@ -226,17 +226,13 @@ public class LevelChunkSection { + // CraftBukkit end + + public void fillBiomesFromNoise(BiomeResolver biomeSupplier, Climate.Sampler sampler, int x, int y, int z) { +- PalettedContainer> datapaletteblock = this.biomes.recreate(); +- boolean flag = true; ++ // Thunderbolt start - Implement noisium; micro optimization ++ PalettedContainer> palette = this.biomes.recreate(); + +- for (int l = 0; l < 4; ++l) { +- for (int i1 = 0; i1 < 4; ++i1) { +- for (int j1 = 0; j1 < 4; ++j1) { +- datapaletteblock.getAndSetUnchecked(l, i1, j1, biomeSupplier.getNoiseBiome(x + l, y + i1, z + j1, sampler)); +- } +- } +- } ++ for (int y1 = 0; y1 < 4; ++y1) for (int z1 = 0; z1 < 4; ++z1) for (int x1 = 0; x1 < 4; ++x1) ++ palette.getAndSetUnchecked(x1, y1, z1, biomeSupplier.getNoiseBiome(x + x1, y + y1, z + z1, sampler)); + +- this.biomes = datapaletteblock; ++ this.biomes = palette; ++ // Thunderbolt end - Implement noisium; micro optimization + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index 81368bf186365878db2e1ed305bb7bf36c26f61f..c1d31b9f37472364d08b07958787410a013619cd 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -29,8 +29,8 @@ public class PalettedContainer implements PaletteResize, PalettedContainer + private final PaletteResize dummyPaletteResize = (newSize, added) -> 0; + public final IdMap registry; + private final T @org.jetbrains.annotations.Nullable [] presetValues; // Paper - Anti-Xray - Add preset values +- private volatile PalettedContainer.Data data; +- private final PalettedContainer.Strategy strategy; ++ public volatile PalettedContainer.Data data; // Thunderbolt - AT (private -> public) ++ public final PalettedContainer.Strategy strategy; // Thunderbolt - AT (private -> public) + // private final ThreadingDetector threadingDetector = new ThreadingDetector("PalettedContainer"); // Paper - unused + + public void acquire() { +@@ -394,7 +394,7 @@ public class PalettedContainer implements PaletteResize, PalettedContainer + void accept(T object, int count); + } + +- static record Data(PalettedContainer.Configuration configuration, BitStorage storage, Palette palette) { ++ public static record Data(PalettedContainer.Configuration configuration, BitStorage storage, Palette palette) { // Thunderbolt - AT (package-private -> public) + public void copyFrom(Palette palette, BitStorage storage) { + for (int i = 0; i < storage.getSize(); i++) { + T object = palette.valueFor(storage.get(i)); +diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +index e3990d5f5a49aca501289e92f7462a5f2709db9b..03cf6ea4091d40cb65d5ecba139e2c0275074cc1 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +@@ -52,6 +52,7 @@ import org.apache.commons.lang3.mutable.MutableObject; + + public final class NoiseBasedChunkGenerator extends ChunkGenerator { + ++ public static boolean NOISIUM = true; // Thunderbolt - Implement noisium + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { + return instance.group(BiomeSource.CODEC.fieldOf("biome_source").forGetter((chunkgeneratorabstract) -> { + return chunkgeneratorabstract.biomeSource; +@@ -274,38 +275,45 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + + @Override + public CompletableFuture fillFromNoise(Executor executor, Blender blender, RandomState noiseConfig, StructureManager structureAccessor, ChunkAccess chunk) { +- NoiseSettings noisesettings = ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().clampToHeightAccessor(chunk.getHeightAccessorForGeneration()); +- int i = noisesettings.minY(); +- int j = Mth.floorDiv(i, noisesettings.getCellHeight()); +- int k = Mth.floorDiv(noisesettings.height(), noisesettings.getCellHeight()); +- +- if (k <= 0) { +- return CompletableFuture.completedFuture(chunk); +- } else { +- int l = chunk.getSectionIndex(k * noisesettings.getCellHeight() - 1 + i); +- int i1 = chunk.getSectionIndex(i); +- Set set = Sets.newHashSet(); +- +- for (int j1 = l; j1 >= i1; --j1) { +- LevelChunkSection chunksection = chunk.getSection(j1); +- +- chunksection.acquire(); +- set.add(chunksection); +- } +- +- return CompletableFuture.supplyAsync(Util.wrapThreadWithTaskName("wgen_fill_noise", () -> { +- return this.doFill(blender, structureAccessor, noiseConfig, chunk, j, k); +- }), executor).whenCompleteAsync((ichunkaccess1, throwable) -> { // Paper - run with supplied executor +- Iterator iterator = set.iterator(); ++ // Thunderbolt start - Implement noisium ++ NoiseSettings settings = this.settings.value().noiseSettings().clampToHeightAccessor(chunk.getHeightAccessorForGeneration()); ++ int minY = settings.minY(); ++ int minYDiv = Mth.floorDiv(minY, settings.getCellHeight()); ++ int cellHeightDiv = Mth.floorDiv(settings.height(), settings.getCellHeight()); ++ ++ if (cellHeightDiv <= 0) return CompletableFuture.completedFuture(chunk); ++ ++ int startIndex = chunk.getSectionIndex(cellHeightDiv * settings.getCellHeight() - 1 + minY); ++ int minYIndex = chunk.getSectionIndex(minY); ++ ++ if (NOISIUM) { ++ LevelChunkSection[] sections = chunk.getSections(); ++ for (int i = startIndex; i >= minYIndex; --i) sections[i].acquire(); ++ ++ return CompletableFuture.supplyAsync(Util.wrapThreadWithTaskName( ++ "wgen_fill_noise", ++ () -> this.doFill(blender, structureAccessor, noiseConfig, chunk, minYDiv, cellHeightDiv) ++ ), Util.backgroundExecutor()).whenCompleteAsync((result, ignored) -> { ++ for (int i = startIndex; i >= minYIndex; --i) sections[i].release(); ++ }, executor); ++ } + +- while (iterator.hasNext()) { +- LevelChunkSection chunksection1 = (LevelChunkSection) iterator.next(); ++ Set set = Sets.newHashSet(); + +- chunksection1.release(); +- } ++ for (int i = startIndex; i >= minYIndex; --i) { ++ LevelChunkSection section = chunk.getSection(i); + +- }, executor); ++ section.acquire(); ++ set.add(section); + } ++ ++ return CompletableFuture.supplyAsync(Util.wrapThreadWithTaskName( ++ "wgen_fill_noise", ++ () -> this.doFill(blender, structureAccessor, noiseConfig, chunk, minYDiv, cellHeightDiv) ++ ), executor).whenCompleteAsync((ignored1, ignored2) -> { ++ for (LevelChunkSection result : set) result.release(); ++ }, executor); ++ // Thunderbolt end + } + + private ChunkAccess doFill(Blender blender, StructureManager structureAccessor, RandomState noiseConfig, ChunkAccess chunk, int minimumCellY, int cellHeight) { +@@ -371,6 +379,20 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + + iblockdata = this.debugPreliminarySurfaceLevel(noisechunk, j4, j3, i5, iblockdata); + if (iblockdata != NoiseBasedChunkGenerator.AIR && !SharedConstants.debugVoidTerrain(chunk.getPos())) { ++ if (NOISIUM) { ++ // Thunderbolt start - Implement noisium ++ chunksection.nonEmptyBlockCount++; ++ ++ if (!iblockdata.getFluidState().isEmpty()) chunksection.nonEmptyBlockCount++; ++ if (iblockdata.isRandomlyTicking()) chunksection.tickingBlockCount++; ++ ++ chunksection.states.data.storage().set( ++ chunksection.states.strategy.getIndex(k4, k3, j5), ++ chunksection.states.data.palette().idFor(iblockdata) ++ ); ++ // Thunderbolt end - Implement noisium ++ } ++ + chunksection.setBlockState(k4, k3, j5, iblockdata, false); + heightmap.update(k4, j3, j5, iblockdata); + heightmap1.update(k4, j3, j5, iblockdata); +diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseSettings.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseSettings.java +index 52fcf1b92854e5c67c51a83d31b4a136413b54e0..e2b07363d4c902739e88927daefbefe24f40891b 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseSettings.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseSettings.java +@@ -8,7 +8,12 @@ import net.minecraft.core.QuartPos; + import net.minecraft.world.level.LevelHeightAccessor; + import net.minecraft.world.level.dimension.DimensionType; + +-public record NoiseSettings(int minY, int height, int noiseSizeHorizontal, int noiseSizeVertical) { ++// Thunderbolt start - Implement noisium ++public record NoiseSettings(int minY, int height, int noiseSizeHorizontal, int noiseSizeVertical, int cellHeight, int cellWidth) { ++ public NoiseSettings(int minY, int height, int noiseSizeHorizontal, int noiseSizeVertical) { ++ this(minY, height, noiseSizeHorizontal, noiseSizeVertical, QuartPos.toBlock(noiseSizeHorizontal), QuartPos.toBlock(noiseSizeVertical)); ++ } ++// Thunderbolt end - Implement noisium + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + Codec.intRange(DimensionType.MIN_Y, DimensionType.MAX_Y).fieldOf("min_y").forGetter(NoiseSettings::minY), +@@ -44,11 +49,11 @@ public record NoiseSettings(int minY, int height, int noiseSizeHorizontal, int n + } + + public int getCellHeight() { +- return QuartPos.toBlock(this.noiseSizeVertical()); ++ return this.cellHeight; // Thunderbolt - Implement noisium + } + + public int getCellWidth() { +- return QuartPos.toBlock(this.noiseSizeHorizontal()); ++ return this.cellWidth; // Thunderbolt - Implement noisium + } + + public NoiseSettings clampToHeightAccessor(LevelHeightAccessor world) { +diff --git a/src/main/java/net/minecraft/world/level/levelgen/material/MaterialRuleList.java b/src/main/java/net/minecraft/world/level/levelgen/material/MaterialRuleList.java +index afdbc74a3012fa717f59ecef613567338d285b7b..23fb7d811772804c7256981bbaca4ad7673a5e31 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/material/MaterialRuleList.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/material/MaterialRuleList.java +@@ -12,9 +12,7 @@ public record MaterialRuleList(List materialRuleLis + public BlockState calculate(DensityFunction.FunctionContext pos) { + for (NoiseChunk.BlockStateFiller blockStateFiller : this.materialRuleList) { + BlockState blockState = blockStateFiller.calculate(pos); +- if (blockState != null) { +- return blockState; +- } ++ if (blockState == null) continue; return blockState; // Thunderbolt - Implement noisium + } + + return null; +diff --git a/src/main/java/org/plazmamc/thunderbolt/configurations/GlobalConfiguration.java b/src/main/java/org/plazmamc/thunderbolt/configurations/GlobalConfiguration.java +index 0b16bbf87a6c5e658e8182e423800acd16dfc7ca..f1cc8de931ff068a387a91d1ae8e2e6cf91036ff 100644 +--- a/src/main/java/org/plazmamc/thunderbolt/configurations/GlobalConfiguration.java ++++ b/src/main/java/org/plazmamc/thunderbolt/configurations/GlobalConfiguration.java +@@ -28,6 +28,7 @@ public class GlobalConfiguration extends ConfigurationPart { + public NeedsReload needsReload; + public class NeedsReload extends ConfigurationPart { + ++ boolean enableNoisium = optimize(); + + @PostProcess + public void post() { +@@ -37,6 +38,7 @@ public class GlobalConfiguration extends ConfigurationPart { + return; + } + ++ net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator.NOISIUM = this.enableNoisium; + } + + } diff --git a/patches/unapplied/api/dropped/.gitkeep b/patches/unapplied/api/dropped/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/patches/unapplied/generated-api/dropped/.gitkeep b/patches/unapplied/generated-api/dropped/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/patches/unapplied/mojang-api/dropped/.gitkeep b/patches/unapplied/mojang-api/dropped/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/patches/unapplied/server/dropped/.gitkeep b/patches/unapplied/server/dropped/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..537f3bb --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,53 @@ +import java.util.Locale + +val projectName = "Thunderbolt" + +pluginManagement { + repositories { + gradlePluginPortal() + maven("https://repo.papermc.io/repository/maven-public/") + } +} + +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" +} + +if (!file(".git").exists()) { + val errorText = """ + + =================================[ ERROR ]================================= + The Thunderbolt project directory is not a properly cloned Git repository. + + In order to build Volt from source you must clone + the repository using Git, not download a code zip from GitHub. + + See https://github.com/PaperMC/Paper/blob/master/CONTRIBUTING.md + for further information on building and modifying Thunderbolt. + =========================================================================== + """.trimIndent() + error(errorText) +} + +if (file("libs").exists()) { + dependencyResolutionManagement { + versionCatalogs { + create("api") { + from(files("libs/api.versions.toml")) + } + create("server") { + from(files("libs/server.versions.toml")) + } + create("common") { + from(files("libs/common.versions.toml")) + } + } + } +} + +rootProject.name = projectName.lowercase() +for (name in listOf("$projectName-API", "$projectName-Server", "$projectName-MojangAPI")) { + val projName = name.lowercase(Locale.ENGLISH) + include(projName) + findProject(":$projName")!!.projectDir = file(name) +}