diff --git a/.github/ISSUE_TEMPLATE/behavior-bug-or-plugin-incompatibility.yml b/.github/ISSUE_TEMPLATE/behavior-bug-or-plugin-incompatibility.yml index 418278c3..c881a955 100644 --- a/.github/ISSUE_TEMPLATE/behavior-bug-or-plugin-incompatibility.yml +++ b/.github/ISSUE_TEMPLATE/behavior-bug-or-plugin-incompatibility.yml @@ -1,8 +1,11 @@ name: Behavior Bug or Plugin Incompatibility description: Report issues with plugin incompatibility or other behavior related issues. labels: [ "status: needs triage", "type: bug" ] +projects: ["OneLiteFeatherNET/6"] +assignees: ["OneLiteFeatherNET/antiredstoneclock-remastered-triage"] body: - type: textarea + id: server-logs attributes: label: Server Logs description: | @@ -10,6 +13,7 @@ body: validations: required: true - type: textarea + id: expected-behavior attributes: label: Expected behavior description: What you expected to see. @@ -17,6 +21,7 @@ body: required: true - type: textarea + id: actual-behavior attributes: label: Actual behavior description: What you actually saw. @@ -24,6 +29,7 @@ body: required: true - type: textarea + id: steps-to-reproduce attributes: label: Steps to reproduce description: This may include a build schematic, a video, or detailed instructions to help reconstruct the issue. @@ -31,6 +37,7 @@ body: required: true - type: textarea + id: plugin-and-datapack-list attributes: label: Plugin and Datapack List description: | @@ -40,6 +47,7 @@ body: required: true - type: textarea + id: paper-version attributes: label: Paper version description: | @@ -61,6 +69,7 @@ body: validations: required: true - type: textarea + id: plugin-version attributes: label: Plugin version description: | @@ -80,6 +89,7 @@ body: validations: required: true - type: textarea + id: other-information attributes: label: Other description: | @@ -89,6 +99,7 @@ body: required: false - type: markdown + id: pre-submission-checklist attributes: value: | Before submitting this issue, please ensure the following: diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index d4c730e8..83cbc7d4 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -1,8 +1,11 @@ name: Feature Request description: Suggest an idea for AntiRedstoneClock-Remastered labels: [ "status: needs triage", "type: feature" ] +projects: ["OneLiteFeatherNET/6"] +assignees: ["OneLiteFeatherNET/antiredstoneclock-remastered-triage"] body: - type: markdown + id: intro attributes: value: | Thank you for filling out a feature request for AntiRedstoneClock-Remastered! Please be as detailed as possible so that we may consider and review the request easier. @@ -10,6 +13,7 @@ body: Before requesting a new feature, please make sure you are using the latest version and that the feature you are requesting is not already in AntiRedstoneClock-Remastered. - type: textarea + id: problem-context attributes: label: Is your feature request related to a problem? description: Please give some context for this request. Why do you want it added? @@ -17,6 +21,7 @@ body: required: true - type: textarea + id: solution-description attributes: label: Describe the solution you'd like. description: A clear and concise description of what you want. @@ -24,6 +29,7 @@ body: required: true - type: textarea + id: alternatives-considered attributes: label: Describe alternatives you've considered. description: List any alternatives you might have tried to get the feature you want. @@ -31,6 +37,7 @@ body: required: true - type: textarea + id: additional-context attributes: label: Other description: Add any other context or screenshots about the feature request below. @@ -38,6 +45,7 @@ body: required: false - type: markdown + id: search-reminder attributes: value: | Before submitting this feature request, please search our issue tracker to ensure your feature has not diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index a4637d47..104b5f29 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -36,13 +36,13 @@ jobs: check_name: "Test Results" comment_title: "Unit Test Results" - name: Upload Test Report - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: always() && matrix.os == 'ubuntu-latest' with: name: test-report path: build/reports/tests/test/ - name: Upload Coverage Reports - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: always() && matrix.os == 'ubuntu-latest' with: name: coverage-report @@ -64,17 +64,17 @@ jobs: distribution: temurin java-version: 24 - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Build run: ./gradlew clean build test - name: Upload JAR for PR - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: pr-jar path: build/libs/*.jar - name: Get JAR Artifact Download URL id: get-artifact-url - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | const runId = context.runId; @@ -88,7 +88,7 @@ jobs: const url = jarArtifact.archive_download_url; core.setOutput('jar_url', url); - name: Create or Update PR Comment with direct JAR download link - uses: peter-evans/create-or-update-comment@v4 + uses: peter-evans/create-or-update-comment@v5 with: token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/label-listener.yml b/.github/workflows/label-listener.yml index 97fe71ab..c508d9cd 100644 --- a/.github/workflows/label-listener.yml +++ b/.github/workflows/label-listener.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check for publish-pr label event - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | const label = context.payload.label?.name; diff --git a/.github/workflows/sematic-releases.yml b/.github/workflows/sematic-releases.yml index c92a6342..f857891e 100644 --- a/.github/workflows/sematic-releases.yml +++ b/.github/workflows/sematic-releases.yml @@ -26,7 +26,7 @@ jobs: with: fetch-depth: 0 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version: "lts/*" - name: Validate Gradle Wrapper diff --git a/CHANGELOG.md b/CHANGELOG.md index b957d341..5a14804f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,63 @@ +## [2.5.2](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/compare/v2.5.1...v2.5.2) (2025-11-03) + + +### Bug Fixes + +* **deps:** update dependency org.junit.jupiter:junit-jupiter to v6.0.1 ([4f2ed87](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/4f2ed87a93be8d24d06306ea96438019a1f26e0d)) +* **deps:** update dependency org.junit.jupiter:junit-jupiter to v6.0.1 ([#199](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/issues/199)) ([69b19bf](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/69b19bf05535a55311ecca21d95a38bde04ed32f)) + +## [2.5.1](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/compare/v2.5.0...v2.5.1) (2025-10-07) + + +### Bug Fixes + +* update field identifier for steps to reproduce in issue template ([193a14c](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/193a14cbb3673287b0e78185055db8244598edcc)) + +# [2.5.0](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/compare/v2.4.0...v2.5.0) (2025-10-07) + + +### Features + +* enhance issue templates with additional fields for better reporting ([c0598f8](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/c0598f832c01b829e926bf8b01315762113710c9)) + +# [2.4.0](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/compare/v2.3.0...v2.4.0) (2025-10-07) + + +### Bug Fixes + +* correct notification configuration keys and method name for clarity ([bf77855](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/bf77855b6cc963b100a8cb9b86f98c182daab4ef)) +* enhance error logging for webhook client creation failures ([201b18e](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/201b18e9d86e657b2dc9da0e1a5f6723236607fa)) +* update Discord notification configuration keys for consistency and improve error handling ([89c46fc](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/89c46fccbe699614fcae5aac05348af1d721c8c1)) + + +### Features + +* add Discord notification service with webhook integration ([c527a2e](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/c527a2e9b24da2e9ff83af853802021a2b6e6401)) +* Add new notification system. ([#177](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/issues/177)) ([afee780](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/afee780e9bf2c2c7ee7d3ad03fa7e2005a4ac3da)) +* enhance notification system with new services and configuration options ([7b2e5ef](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/7b2e5efb46dca0a3dc2bff98342b6c0e27e69425)) +* implement notification system for redstone clock detection ([9a42292](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/9a422921687670fa53af6365fe9498d1f0f1d99a)) +* implement sign block break handling and metadata management ([d737be4](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/d737be4be32760383b588ffd6bb9736c2b54a41a)) +* improve Discord webhook handling and error logging ([b9f196b](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/b9f196b8bb839f96e7d3b805710150136b7f5497)) + +# [2.4.0](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/compare/v2.3.0...v2.4.0) (2025-10-07) + + +### Bug Fixes + +* correct notification configuration keys and method name for clarity ([bf77855](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/bf77855b6cc963b100a8cb9b86f98c182daab4ef)) +* enhance error logging for webhook client creation failures ([201b18e](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/201b18e9d86e657b2dc9da0e1a5f6723236607fa)) +* update Discord notification configuration keys for consistency and improve error handling ([89c46fc](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/89c46fccbe699614fcae5aac05348af1d721c8c1)) + + +### Features + +* add Discord notification service with webhook integration ([c527a2e](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/c527a2e9b24da2e9ff83af853802021a2b6e6401)) +* Add new notification system. ([#177](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/issues/177)) ([afee780](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/afee780e9bf2c2c7ee7d3ad03fa7e2005a4ac3da)) +* enhance notification system with new services and configuration options ([7b2e5ef](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/7b2e5efb46dca0a3dc2bff98342b6c0e27e69425)) +* implement notification system for redstone clock detection ([9a42292](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/9a422921687670fa53af6365fe9498d1f0f1d99a)) +* implement sign block break handling and metadata management ([d737be4](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/d737be4be32760383b588ffd6bb9736c2b54a41a)) +* improve Discord webhook handling and error logging ([b9f196b](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/commit/b9f196b8bb839f96e7d3b805710150136b7f5497)) + # [2.4.0](https://github.com/OneLiteFeatherNET/AntiRedstoneClock-Remastered/compare/v2.3.0...v2.4.0) (2025-10-03) diff --git a/SERVICE_ARCHITECTURE.md b/SERVICE_ARCHITECTURE.md index 859b0a8f..eeec5d5b 100644 --- a/SERVICE_ARCHITECTURE.md +++ b/SERVICE_ARCHITECTURE.md @@ -117,7 +117,7 @@ The plugin automatically selects the appropriate implementation: ```java // In AntiRedstoneClockRemastered.java private void enableRedstoneClockService() { - this.redstoneClockService = RedstoneClockServiceFactory.createService(this); + this.decisionService = RedstoneClockServiceFactory.createService(this); } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 97243655..d50a7648 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -35,6 +35,8 @@ val supportedMinecraftVersions = listOf( "1.21.6", "1.21.7", "1.21.8", + "1.21.9", + "1.21.10" ) allprojects { apply { @@ -64,7 +66,7 @@ dependencies { implementation(libs.adventure.text.feature.pagination) implementation(libs.adventure.text.discord) implementation(libs.jda.webhook) - implementation(libs.jda) + implementation(libs.customblockdata) implementation(libs.guice) implementation(libs.jakarta.inject) annotationProcessor(libs.cloud.command.annotations) @@ -130,6 +132,7 @@ tasks { shadowJar { archiveClassifier.set("") relocate("org.bstats", "net.onelitefeather.antiredstoneclockremastered.org.bstats") + relocate("com.jeff_media.customblockdata", "net.onelitefeather.antiredstoneclockremastered.com.jeff_media.customblockdata") dependsOn(jar) } this.modrinth { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 8bdaf60c..f8e1ee31 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e111328..bad7c246 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/package-lock.json b/package-lock.json index 3fbda485..22df1f6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,9 +12,48 @@ "@semantic-release/release-notes-generator": "^14.0.3", "conventional-changelog-angular": "^8.0.0", "conventional-changelog-conventionalcommits": "^9.0.0", - "semantic-release": "^24.2.7" + "semantic-release": "^25.0.0" } }, + "node_modules/@actions/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/exec": "^1.1.1", + "@actions/http-client": "^2.0.1" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -51,42 +90,14 @@ "node": ">=0.1.90" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", "dev": true, "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, "engines": { - "node": ">= 8" + "node": ">=14" } }, "node_modules/@octokit/auth-token": { @@ -505,9 +516,9 @@ } }, "node_modules/@semantic-release/github": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.3.tgz", - "integrity": "sha512-T2fKUyFkHHkUNa5XNmcsEcDPuG23hwBKptfUVcFXDVG2cSjXXZYDOfVYwfouqbWo/8UefotLaoGfQeK+k3ep6A==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-12.0.0.tgz", + "integrity": "sha512-louWFjzZ+1dogfJTY8IuJuBcBUOTliYhBUYNcomnTfj0i959wtRQbr1POgdCoTHK7ut4N/0LNlYTH8SvSJM3hg==", "dev": true, "license": "MIT", "dependencies": { @@ -519,17 +530,17 @@ "aggregate-error": "^5.0.0", "debug": "^4.3.4", "dir-glob": "^3.0.1", - "globby": "^14.0.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "issue-parser": "^7.0.0", "lodash-es": "^4.17.21", "mime": "^4.0.0", "p-filter": "^4.0.0", + "tinyglobby": "^0.2.14", "url-join": "^5.0.0" }, "engines": { - "node": ">=20.8.1" + "node": "^22.14.0 || >= 24.10.0" }, "peerDependencies": { "semantic-release": ">=24.1.0" @@ -582,20 +593,22 @@ } }, "node_modules/@semantic-release/npm": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-12.0.2.tgz", - "integrity": "sha512-+M9/Lb35IgnlUO6OSJ40Ie+hUsZLuph2fqXC/qrKn0fMvUU/jiCjpoL6zEm69vzcmaZJ8yNKtMBEKHWN49WBbQ==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-13.1.1.tgz", + "integrity": "sha512-c4tlp3STYaTYORmMcLjiTaI8SLoxJ0Uf7IXkem8EyihuOM624wnaGuH4OuY2HHcsHDerNAQNzZ8VO6d4PMHSzA==", "dev": true, "license": "MIT", "dependencies": { + "@actions/core": "^1.11.1", "@semantic-release/error": "^4.0.0", "aggregate-error": "^5.0.0", + "env-ci": "^11.2.0", "execa": "^9.0.0", "fs-extra": "^11.0.0", "lodash-es": "^4.17.21", "nerf-dart": "^1.0.0", "normalize-url": "^8.0.0", - "npm": "^10.9.3", + "npm": "^11.6.2", "rc": "^1.2.8", "read-pkg": "^9.0.0", "registry-auth-token": "^5.0.0", @@ -603,7 +616,7 @@ "tempy": "^3.0.0" }, "engines": { - "node": ">=20.8.1" + "node": "^22.14.0 || >= 24.10.0" }, "peerDependencies": { "semantic-release": ">=20.1.0" @@ -977,18 +990,90 @@ } }, "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "dev": true, "license": "ISC", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" }, "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/color-convert": { @@ -1034,9 +1119,9 @@ } }, "node_modules/conventional-changelog-angular": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.0.0.tgz", - "integrity": "sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.1.0.tgz", + "integrity": "sha512-GGf2Nipn1RUCAktxuVauVr1e3r8QrLP/B0lEUsFktmGqc3ddbQkhoJZHJctVU829U1c6mTSWftrVOCHaL85Q3w==", "dev": true, "license": "ISC", "dependencies": { @@ -1293,9 +1378,9 @@ "license": "MIT" }, "node_modules/env-ci": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.1.1.tgz", - "integrity": "sha512-mT3ks8F0kwpo7SYNds6nWj0PaRh+qJxIeBVBXAKTN9hphAzZv7s0QAZQbqnB1fAv/r4pJUGE15BV9UrS31FP2w==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.2.0.tgz", + "integrity": "sha512-D5kWfzkmaOQDioPmiviWAVtKmpPT4/iJmMVQxWxMPJTFyTkdc5JQUfc5iXEeWxcOdsYTKSAiA/Age4NUOqKsRA==", "dev": true, "license": "MIT", "dependencies": { @@ -1554,33 +1639,6 @@ ], "license": "MIT" }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, "node_modules/figures": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", @@ -1702,6 +1760,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-stream": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-7.0.1.tgz", @@ -1730,66 +1801,6 @@ "traverse": "0.6.8" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globby": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", - "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.3", - "ignore": "^7.0.3", - "path-type": "^6.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -1903,16 +1914,6 @@ "node": ">=18.18.0" } }, - "node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -2026,16 +2027,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -2046,19 +2037,6 @@ "node": ">=8" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2369,16 +2347,6 @@ "dev": true, "license": "MIT" }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -2507,9 +2475,9 @@ } }, "node_modules/npm": { - "version": "10.9.3", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.9.3.tgz", - "integrity": "sha512-6Eh1u5Q+kIVXeA8e7l2c/HpnFFcwrkt37xDMujD5be1gloWa9p6j3Fsv3mByXXmqJHy+2cElRMML8opNT7xIJQ==", + "version": "11.6.2", + "resolved": "https://registry.npmjs.org/npm/-/npm-11.6.2.tgz", + "integrity": "sha512-7iKzNfy8lWYs3zq4oFPa8EXZz5xt9gQNKJZau3B1ErLBb6bF7sBJ00x09485DOvRT2l5Gerbl3VlZNT57MxJVA==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -2540,7 +2508,6 @@ "libnpmdiff", "libnpmexec", "libnpmfund", - "libnpmhook", "libnpmorg", "libnpmpack", "libnpmpublish", @@ -2554,7 +2521,6 @@ "ms", "node-gyp", "nopt", - "normalize-package-data", "npm-audit-report", "npm-install-checks", "npm-package-arg", @@ -2577,8 +2543,7 @@ "tiny-relative-date", "treeverse", "validate-npm-package-name", - "which", - "write-file-atomic" + "which" ], "dev": true, "license": "Artistic-2.0", @@ -2591,80 +2556,77 @@ ], "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^8.0.1", - "@npmcli/config": "^9.0.0", + "@npmcli/arborist": "^9.1.6", + "@npmcli/config": "^10.4.2", "@npmcli/fs": "^4.0.0", - "@npmcli/map-workspaces": "^4.0.2", - "@npmcli/package-json": "^6.2.0", - "@npmcli/promise-spawn": "^8.0.2", + "@npmcli/map-workspaces": "^5.0.0", + "@npmcli/package-json": "^7.0.1", + "@npmcli/promise-spawn": "^8.0.3", "@npmcli/redact": "^3.2.2", - "@npmcli/run-script": "^9.1.0", - "@sigstore/tuf": "^3.1.1", + "@npmcli/run-script": "^10.0.0", + "@sigstore/tuf": "^4.0.0", "abbrev": "^3.0.1", "archy": "~1.0.0", - "cacache": "^19.0.1", - "chalk": "^5.4.1", - "ci-info": "^4.2.0", + "cacache": "^20.0.1", + "chalk": "^5.6.2", + "ci-info": "^4.3.1", "cli-columns": "^4.0.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", - "glob": "^10.4.5", + "glob": "^11.0.3", "graceful-fs": "^4.2.11", - "hosted-git-info": "^8.1.0", + "hosted-git-info": "^9.0.2", "ini": "^5.0.0", - "init-package-json": "^7.0.2", - "is-cidr": "^5.1.1", + "init-package-json": "^8.2.2", + "is-cidr": "^6.0.1", "json-parse-even-better-errors": "^4.0.0", - "libnpmaccess": "^9.0.0", - "libnpmdiff": "^7.0.1", - "libnpmexec": "^9.0.1", - "libnpmfund": "^6.0.1", - "libnpmhook": "^11.0.0", - "libnpmorg": "^7.0.0", - "libnpmpack": "^8.0.1", - "libnpmpublish": "^10.0.1", - "libnpmsearch": "^8.0.0", - "libnpmteam": "^7.0.0", - "libnpmversion": "^7.0.0", - "make-fetch-happen": "^14.0.3", - "minimatch": "^9.0.5", + "libnpmaccess": "^10.0.3", + "libnpmdiff": "^8.0.9", + "libnpmexec": "^10.1.8", + "libnpmfund": "^7.0.9", + "libnpmorg": "^8.0.1", + "libnpmpack": "^9.0.9", + "libnpmpublish": "^11.1.2", + "libnpmsearch": "^9.0.1", + "libnpmteam": "^8.0.2", + "libnpmversion": "^8.0.2", + "make-fetch-happen": "^15.0.2", + "minimatch": "^10.0.3", "minipass": "^7.1.1", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", - "node-gyp": "^11.2.0", + "node-gyp": "^11.4.2", "nopt": "^8.1.0", - "normalize-package-data": "^7.0.0", "npm-audit-report": "^6.0.0", - "npm-install-checks": "^7.1.1", - "npm-package-arg": "^12.0.2", - "npm-pick-manifest": "^10.0.0", - "npm-profile": "^11.0.1", - "npm-registry-fetch": "^18.0.2", + "npm-install-checks": "^7.1.2", + "npm-package-arg": "^13.0.1", + "npm-pick-manifest": "^11.0.1", + "npm-profile": "^12.0.0", + "npm-registry-fetch": "^19.0.0", "npm-user-validate": "^3.0.0", "p-map": "^7.0.3", - "pacote": "^19.0.1", + "pacote": "^21.0.3", "parse-conflict-json": "^4.0.0", "proc-log": "^5.0.0", "qrcode-terminal": "^0.12.0", "read": "^4.1.0", - "semver": "^7.7.2", + "semver": "^7.7.3", "spdx-expression-parse": "^4.0.0", "ssri": "^12.0.0", - "supports-color": "^9.4.0", - "tar": "^6.2.1", + "supports-color": "^10.2.2", + "tar": "^7.5.1", "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", + "tiny-relative-date": "^2.0.2", "treeverse": "^3.0.0", - "validate-npm-package-name": "^6.0.1", - "which": "^5.0.0", - "write-file-atomic": "^6.0.0" + "validate-npm-package-name": "^6.0.2", + "which": "^5.0.0" }, "bin": { "npm": "bin/npm-cli.js", "npx": "bin/npx-cli.js" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm-run-path": { @@ -2697,6 +2659,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/npm/node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/npm/node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/npm/node_modules/@isaacs/cliui": { "version": "8.0.2", "dev": true, @@ -2715,7 +2698,7 @@ } }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", + "version": "6.2.2", "dev": true, "inBundle": true, "license": "MIT", @@ -2750,7 +2733,7 @@ } }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", + "version": "7.1.2", "dev": true, "inBundle": true, "license": "MIT", @@ -2783,7 +2766,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/@npmcli/agent": { - "version": "3.0.0", + "version": "4.0.0", "dev": true, "inBundle": true, "license": "ISC", @@ -2791,15 +2774,15 @@ "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", + "lru-cache": "^11.2.1", "socks-proxy-agent": "^8.0.3" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "8.0.1", + "version": "9.1.6", "dev": true, "inBundle": true, "license": "ISC", @@ -2807,63 +2790,61 @@ "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/fs": "^4.0.0", "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/map-workspaces": "^4.0.1", - "@npmcli/metavuln-calculator": "^8.0.0", + "@npmcli/map-workspaces": "^5.0.0", + "@npmcli/metavuln-calculator": "^9.0.2", "@npmcli/name-from-folder": "^3.0.0", "@npmcli/node-gyp": "^4.0.0", - "@npmcli/package-json": "^6.0.1", + "@npmcli/package-json": "^7.0.0", "@npmcli/query": "^4.0.0", "@npmcli/redact": "^3.0.0", - "@npmcli/run-script": "^9.0.1", + "@npmcli/run-script": "^10.0.0", "bin-links": "^5.0.0", - "cacache": "^19.0.1", + "cacache": "^20.0.1", "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^8.0.0", - "json-parse-even-better-errors": "^4.0.0", + "hosted-git-info": "^9.0.0", "json-stringify-nice": "^1.1.4", - "lru-cache": "^10.2.2", - "minimatch": "^9.0.4", + "lru-cache": "^11.2.1", + "minimatch": "^10.0.3", "nopt": "^8.0.0", "npm-install-checks": "^7.1.0", - "npm-package-arg": "^12.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.1", - "pacote": "^19.0.0", + "npm-package-arg": "^13.0.0", + "npm-pick-manifest": "^11.0.1", + "npm-registry-fetch": "^19.0.0", + "pacote": "^21.0.2", "parse-conflict-json": "^4.0.0", "proc-log": "^5.0.0", "proggy": "^3.0.0", "promise-all-reject-late": "^1.0.0", "promise-call-limit": "^3.0.1", - "read-package-json-fast": "^4.0.0", "semver": "^7.3.7", "ssri": "^12.0.0", "treeverse": "^3.0.0", - "walk-up-path": "^3.0.1" + "walk-up-path": "^4.0.0" }, "bin": { "arborist": "bin/index.js" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@npmcli/config": { - "version": "9.0.0", + "version": "10.4.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/map-workspaces": "^4.0.1", - "@npmcli/package-json": "^6.0.1", + "@npmcli/map-workspaces": "^5.0.0", + "@npmcli/package-json": "^7.0.0", "ci-info": "^4.0.0", "ini": "^5.0.0", - "nopt": "^8.0.0", + "nopt": "^8.1.0", "proc-log": "^5.0.0", "semver": "^7.3.5", - "walk-up-path": "^3.0.1" + "walk-up-path": "^4.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@npmcli/fs": { @@ -2879,22 +2860,22 @@ } }, "node_modules/npm/node_modules/@npmcli/git": { - "version": "6.0.3", + "version": "7.0.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/promise-spawn": "^8.0.0", "ini": "^5.0.0", - "lru-cache": "^10.0.1", - "npm-pick-manifest": "^10.0.0", + "lru-cache": "^11.2.1", + "npm-pick-manifest": "^11.0.1", "proc-log": "^5.0.0", "promise-retry": "^2.0.1", "semver": "^7.3.5", "which": "^5.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@npmcli/installed-package-contents": { @@ -2914,69 +2895,38 @@ } }, "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "4.0.2", + "version": "5.0.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/name-from-folder": "^3.0.0", - "@npmcli/package-json": "^6.0.0", - "glob": "^10.2.2", - "minimatch": "^9.0.0" + "@npmcli/package-json": "^7.0.0", + "glob": "^11.0.3", + "minimatch": "^10.0.3" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "8.0.1", + "version": "9.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "cacache": "^19.0.0", + "cacache": "^20.0.0", "json-parse-even-better-errors": "^4.0.0", - "pacote": "^20.0.0", + "pacote": "^21.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm/node_modules/@npmcli/metavuln-calculator/node_modules/pacote": { - "version": "20.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/package-json": "^6.0.0", - "@npmcli/promise-spawn": "^8.0.0", - "@npmcli/run-script": "^9.0.0", - "cacache": "^19.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^12.0.0", - "npm-packlist": "^9.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^3.0.0", - "ssri": "^12.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "bin/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/name-from-folder": { - "version": "3.0.0", + "node_modules/npm/node_modules/@npmcli/name-from-folder": { + "version": "3.0.0", "dev": true, "inBundle": true, "license": "ISC", @@ -2994,25 +2944,25 @@ } }, "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "6.2.0", + "version": "7.0.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/git": "^6.0.0", - "glob": "^10.2.2", - "hosted-git-info": "^8.0.0", + "@npmcli/git": "^7.0.0", + "glob": "^11.0.3", + "hosted-git-info": "^9.0.0", "json-parse-even-better-errors": "^4.0.0", "proc-log": "^5.0.0", "semver": "^7.5.3", "validate-npm-package-license": "^3.0.4" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "8.0.2", + "version": "8.0.3", "dev": true, "inBundle": true, "license": "ISC", @@ -3045,20 +2995,20 @@ } }, "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "9.1.0", + "version": "10.0.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/node-gyp": "^4.0.0", - "@npmcli/package-json": "^6.0.0", + "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^8.0.0", "node-gyp": "^11.0.0", "proc-log": "^5.0.0", "which": "^5.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@pkgjs/parseargs": { @@ -3071,8 +3021,29 @@ "node": ">=14" } }, + "node_modules/npm/node_modules/@sigstore/bundle": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.5.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm/node_modules/@sigstore/core": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/npm/node_modules/@sigstore/protobuf-specs": { - "version": "0.4.3", + "version": "0.5.0", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -3080,17 +3051,48 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/npm/node_modules/@sigstore/sign": { + "version": "4.0.1", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.0.0", + "@sigstore/protobuf-specs": "^0.5.0", + "make-fetch-happen": "^15.0.2", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "3.1.1", + "version": "4.0.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/protobuf-specs": "^0.4.1", - "tuf-js": "^3.0.1" + "@sigstore/protobuf-specs": "^0.5.0", + "tuf-js": "^4.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm/node_modules/@sigstore/verify": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.0.0", + "@sigstore/protobuf-specs": "^0.5.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@tufjs/canonical-json": { @@ -3102,6 +3104,34 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/npm/node_modules/@tufjs/models": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.5" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm/node_modules/@tufjs/models/node_modules/minimatch": { + "version": "9.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/npm/node_modules/abbrev": { "version": "3.0.1", "dev": true, @@ -3112,7 +3142,7 @@ } }, "node_modules/npm/node_modules/agent-base": { - "version": "7.1.3", + "version": "7.1.4", "dev": true, "inBundle": true, "license": "MIT", @@ -3130,7 +3160,7 @@ } }, "node_modules/npm/node_modules/ansi-styles": { - "version": "6.2.1", + "version": "6.2.3", "dev": true, "inBundle": true, "license": "MIT", @@ -3142,7 +3172,7 @@ } }, "node_modules/npm/node_modules/aproba": { - "version": "2.0.0", + "version": "2.1.0", "dev": true, "inBundle": true, "license": "ISC" @@ -3176,12 +3206,12 @@ } }, "node_modules/npm/node_modules/binary-extensions": { - "version": "2.3.0", + "version": "3.1.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3197,80 +3227,29 @@ } }, "node_modules/npm/node_modules/cacache": { - "version": "19.0.1", + "version": "20.0.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", + "glob": "^11.0.3", + "lru-cache": "^11.1.0", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^12.0.0", - "tar": "^7.4.3", "unique-filename": "^4.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/chownr": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/mkdirp": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/tar": { - "version": "7.4.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/yallist": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/chalk": { - "version": "5.4.1", + "version": "5.6.2", "dev": true, "inBundle": true, "license": "MIT", @@ -3282,16 +3261,16 @@ } }, "node_modules/npm/node_modules/chownr": { - "version": "2.0.0", + "version": "3.0.0", "dev": true, "inBundle": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/npm/node_modules/ci-info": { - "version": "4.2.0", + "version": "4.3.1", "dev": true, "funding": [ { @@ -3306,15 +3285,15 @@ } }, "node_modules/npm/node_modules/cidr-regex": { - "version": "4.1.3", + "version": "5.0.1", "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { - "ip-regex": "^5.0.0" + "ip-regex": "5.0.0" }, "engines": { - "node": ">=14" + "node": ">=20" } }, "node_modules/npm/node_modules/cli-columns": { @@ -3377,6 +3356,12 @@ "node": ">= 8" } }, + "node_modules/npm/node_modules/cross-spawn/node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, "node_modules/npm/node_modules/cross-spawn/node_modules/which": { "version": "2.0.2", "dev": true, @@ -3405,7 +3390,7 @@ } }, "node_modules/npm/node_modules/debug": { - "version": "4.4.1", + "version": "4.4.3", "dev": true, "inBundle": true, "license": "MIT", @@ -3422,7 +3407,7 @@ } }, "node_modules/npm/node_modules/diff": { - "version": "5.2.0", + "version": "8.0.2", "dev": true, "inBundle": true, "license": "BSD-3-Clause", @@ -3511,21 +3496,24 @@ } }, "node_modules/npm/node_modules/glob": { - "version": "10.4.5", + "version": "11.0.3", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" }, + "engines": { + "node": "20 || >=22" + }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -3537,15 +3525,15 @@ "license": "ISC" }, "node_modules/npm/node_modules/hosted-git-info": { - "version": "8.1.0", + "version": "9.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "lru-cache": "^10.0.1" + "lru-cache": "^11.1.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/http-cache-semantics": { @@ -3594,15 +3582,15 @@ } }, "node_modules/npm/node_modules/ignore-walk": { - "version": "7.0.0", + "version": "8.0.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "minimatch": "^9.0.0" + "minimatch": "^10.0.3" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/imurmurhash": { @@ -3624,32 +3612,28 @@ } }, "node_modules/npm/node_modules/init-package-json": { - "version": "7.0.2", + "version": "8.2.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/package-json": "^6.0.0", - "npm-package-arg": "^12.0.0", + "@npmcli/package-json": "^7.0.0", + "npm-package-arg": "^13.0.0", "promzard": "^2.0.0", "read": "^4.0.0", - "semver": "^7.3.5", + "semver": "^7.7.2", "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^6.0.0" + "validate-npm-package-name": "^6.0.2" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/ip-address": { - "version": "9.0.5", + "version": "10.0.1", "dev": true, "inBundle": true, "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, "engines": { "node": ">= 12" } @@ -3667,15 +3651,15 @@ } }, "node_modules/npm/node_modules/is-cidr": { - "version": "5.1.1", + "version": "6.0.1", "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { - "cidr-regex": "^4.1.1" + "cidr-regex": "5.0.1" }, "engines": { - "node": ">=14" + "node": ">=20" } }, "node_modules/npm/node_modules/is-fullwidth-code-point": { @@ -3688,32 +3672,29 @@ } }, "node_modules/npm/node_modules/isexe": { - "version": "2.0.0", + "version": "3.1.1", "dev": true, "inBundle": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": ">=16" + } }, "node_modules/npm/node_modules/jackspeak": { - "version": "3.4.3", + "version": "4.1.1", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, + "engines": { + "node": "20 || >=22" + }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/npm/node_modules/jsbn": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, "node_modules/npm/node_modules/json-parse-even-better-errors": { "version": "4.0.0", "dev": true, @@ -3754,185 +3735,177 @@ "license": "MIT" }, "node_modules/npm/node_modules/libnpmaccess": { - "version": "9.0.0", + "version": "10.0.3", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "npm-package-arg": "^12.0.0", - "npm-registry-fetch": "^18.0.1" + "npm-package-arg": "^13.0.0", + "npm-registry-fetch": "^19.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/libnpmdiff": { - "version": "7.0.1", + "version": "8.0.9", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^8.0.1", + "@npmcli/arborist": "^9.1.6", "@npmcli/installed-package-contents": "^3.0.0", - "binary-extensions": "^2.3.0", - "diff": "^5.1.0", - "minimatch": "^9.0.4", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0", - "tar": "^6.2.1" + "binary-extensions": "^3.0.0", + "diff": "^8.0.2", + "minimatch": "^10.0.3", + "npm-package-arg": "^13.0.0", + "pacote": "^21.0.2", + "tar": "^7.5.1" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/libnpmexec": { - "version": "9.0.1", + "version": "10.1.8", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^8.0.1", - "@npmcli/run-script": "^9.0.1", + "@npmcli/arborist": "^9.1.6", + "@npmcli/package-json": "^7.0.0", + "@npmcli/run-script": "^10.0.0", "ci-info": "^4.0.0", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0", + "npm-package-arg": "^13.0.0", + "pacote": "^21.0.2", "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", "read": "^4.0.0", - "read-package-json-fast": "^4.0.0", "semver": "^7.3.7", - "walk-up-path": "^3.0.1" + "signal-exit": "^4.1.0", + "walk-up-path": "^4.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/libnpmfund": { - "version": "6.0.1", + "version": "7.0.9", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^8.0.1" + "@npmcli/arborist": "^9.1.6" }, "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmhook": { - "version": "11.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/libnpmorg": { - "version": "7.0.0", + "version": "8.0.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" + "npm-registry-fetch": "^19.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/libnpmpack": { - "version": "8.0.1", + "version": "9.0.9", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^8.0.1", - "@npmcli/run-script": "^9.0.1", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0" + "@npmcli/arborist": "^9.1.6", + "@npmcli/run-script": "^10.0.0", + "npm-package-arg": "^13.0.0", + "pacote": "^21.0.2" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/libnpmpublish": { - "version": "10.0.1", + "version": "11.1.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { + "@npmcli/package-json": "^7.0.0", "ci-info": "^4.0.0", - "normalize-package-data": "^7.0.0", - "npm-package-arg": "^12.0.0", - "npm-registry-fetch": "^18.0.1", + "npm-package-arg": "^13.0.0", + "npm-registry-fetch": "^19.0.0", "proc-log": "^5.0.0", "semver": "^7.3.7", - "sigstore": "^3.0.0", + "sigstore": "^4.0.0", "ssri": "^12.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/libnpmsearch": { - "version": "8.0.0", + "version": "9.0.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "npm-registry-fetch": "^18.0.1" + "npm-registry-fetch": "^19.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/libnpmteam": { - "version": "7.0.0", + "version": "8.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" + "npm-registry-fetch": "^19.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/libnpmversion": { - "version": "7.0.0", + "version": "8.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/git": "^6.0.1", - "@npmcli/run-script": "^9.0.1", + "@npmcli/git": "^7.0.0", + "@npmcli/run-script": "^10.0.0", "json-parse-even-better-errors": "^4.0.0", "proc-log": "^5.0.0", "semver": "^7.3.7" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/lru-cache": { - "version": "10.4.3", + "version": "11.2.2", "dev": true, "inBundle": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "20 || >=22" + } }, "node_modules/npm/node_modules/make-fetch-happen": { - "version": "14.0.3", + "version": "15.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/agent": "^3.0.0", - "cacache": "^19.0.1", + "@npmcli/agent": "^4.0.0", + "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^4.0.0", @@ -3944,28 +3917,19 @@ "ssri": "^12.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/make-fetch-happen/node_modules/negotiator": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/minimatch": { - "version": "9.0.5", + "version": "10.0.3", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "@isaacs/brace-expansion": "^5.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4082,7 +4046,7 @@ } }, "node_modules/npm/node_modules/minizlib": { - "version": "3.0.2", + "version": "3.1.0", "dev": true, "inBundle": true, "license": "MIT", @@ -4093,18 +4057,6 @@ "node": ">= 18" } }, - "node_modules/npm/node_modules/mkdirp": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/npm/node_modules/ms": { "version": "2.1.3", "dev": true, @@ -4120,8 +4072,17 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/npm/node_modules/negotiator": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/npm/node_modules/node-gyp": { - "version": "11.2.0", + "version": "11.4.2", "dev": true, "inBundle": true, "license": "MIT", @@ -4144,54 +4105,137 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/chownr": { + "node_modules/npm/node_modules/node-gyp/node_modules/@npmcli/agent": { "version": "3.0.0", "dev": true, "inBundle": true, - "license": "BlueOak-1.0.0", + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, "engines": { - "node": ">=18" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/mkdirp": { - "version": "3.0.1", + "node_modules/npm/node_modules/node-gyp/node_modules/cacache": { + "version": "19.0.1", "dev": true, "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^4.0.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": ">=10" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/glob": { + "version": "10.4.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/jackspeak": { + "version": "3.4.3", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" }, "funding": { "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/tar": { - "version": "7.4.3", + "node_modules/npm/node_modules/node-gyp/node_modules/lru-cache": { + "version": "10.4.3", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/node-gyp/node_modules/make-fetch-happen": { + "version": "14.0.3", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "ssri": "^12.0.0" }, "engines": { - "node": ">=18" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/yallist": { - "version": "5.0.0", + "node_modules/npm/node_modules/node-gyp/node_modules/minimatch": { + "version": "9.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/path-scurry": { + "version": "1.11.1", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, "engines": { - "node": ">=18" + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/npm/node_modules/nopt": { @@ -4209,20 +4253,6 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/normalize-package-data": { - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^8.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, "node_modules/npm/node_modules/npm-audit-report": { "version": "6.0.0", "dev": true, @@ -4245,7 +4275,7 @@ } }, "node_modules/npm/node_modules/npm-install-checks": { - "version": "7.1.1", + "version": "7.1.2", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -4266,77 +4296,78 @@ } }, "node_modules/npm/node_modules/npm-package-arg": { - "version": "12.0.2", + "version": "13.0.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "hosted-git-info": "^8.0.0", + "hosted-git-info": "^9.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^6.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/npm-packlist": { - "version": "9.0.0", + "version": "10.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "ignore-walk": "^7.0.0" + "ignore-walk": "^8.0.0", + "proc-log": "^5.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "10.0.0", + "version": "11.0.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "npm-install-checks": "^7.1.0", "npm-normalize-package-bin": "^4.0.0", - "npm-package-arg": "^12.0.0", + "npm-package-arg": "^13.0.0", "semver": "^7.3.5" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/npm-profile": { - "version": "11.0.1", + "version": "12.0.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "npm-registry-fetch": "^18.0.0", + "npm-registry-fetch": "^19.0.0", "proc-log": "^5.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "18.0.2", + "version": "19.0.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/redact": "^3.0.0", "jsonparse": "^1.3.1", - "make-fetch-happen": "^14.0.0", + "make-fetch-happen": "^15.0.0", "minipass": "^7.0.2", "minipass-fetch": "^4.0.0", "minizlib": "^3.0.1", - "npm-package-arg": "^12.0.0", + "npm-package-arg": "^13.0.0", "proc-log": "^5.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/npm-user-validate": { @@ -4367,34 +4398,34 @@ "license": "BlueOak-1.0.0" }, "node_modules/npm/node_modules/pacote": { - "version": "19.0.1", + "version": "21.0.3", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/git": "^6.0.0", + "@npmcli/git": "^7.0.0", "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/package-json": "^6.0.0", + "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^8.0.0", - "@npmcli/run-script": "^9.0.0", - "cacache": "^19.0.0", + "@npmcli/run-script": "^10.0.0", + "cacache": "^20.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", - "npm-package-arg": "^12.0.0", - "npm-packlist": "^9.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.0", + "npm-package-arg": "^13.0.0", + "npm-packlist": "^10.0.1", + "npm-pick-manifest": "^11.0.1", + "npm-registry-fetch": "^19.0.0", "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "sigstore": "^3.0.0", + "sigstore": "^4.0.0", "ssri": "^12.0.0", - "tar": "^6.1.11" + "tar": "^7.4.3" }, "bin": { "pacote": "bin/index.js" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/parse-conflict-json": { @@ -4421,16 +4452,16 @@ } }, "node_modules/npm/node_modules/path-scurry": { - "version": "1.11.1", + "version": "2.0.0", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4539,19 +4570,6 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/read-package-json-fast": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^4.0.0", - "npm-normalize-package-bin": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, "node_modules/npm/node_modules/retry": { "version": "0.12.0", "dev": true, @@ -4569,7 +4587,7 @@ "optional": true }, "node_modules/npm/node_modules/semver": { - "version": "7.7.2", + "version": "7.7.3", "dev": true, "inBundle": true, "license": "ISC", @@ -4596,90 +4614,38 @@ "version": "3.0.0", "dev": true, "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/signal-exit": { - "version": "4.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/sigstore": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^3.1.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.4.0", - "@sigstore/sign": "^3.1.0", - "@sigstore/tuf": "^3.1.0", - "@sigstore/verify": "^2.1.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/bundle": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.4.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/core": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=8" } }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/sign": { - "version": "3.1.0", + "node_modules/npm/node_modules/signal-exit": { + "version": "4.1.0", "dev": true, "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^3.1.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.4.0", - "make-fetch-happen": "^14.0.2", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1" - }, + "license": "ISC", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/verify": { - "version": "2.1.1", + "node_modules/npm/node_modules/sigstore": { + "version": "4.0.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^3.1.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.4.1" + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.0.0", + "@sigstore/protobuf-specs": "^0.5.0", + "@sigstore/sign": "^4.0.0", + "@sigstore/tuf": "^4.0.0", + "@sigstore/verify": "^3.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/smart-buffer": { @@ -4693,12 +4659,12 @@ } }, "node_modules/npm/node_modules/socks": { - "version": "2.8.5", + "version": "2.8.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", + "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" }, "engines": { @@ -4757,17 +4723,11 @@ } }, "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.21", + "version": "3.0.22", "dev": true, "inBundle": true, "license": "CC0-1.0" }, - "node_modules/npm/node_modules/sprintf-js": { - "version": "1.1.3", - "dev": true, - "inBundle": true, - "license": "BSD-3-Clause" - }, "node_modules/npm/node_modules/ssri": { "version": "12.0.0", "dev": true, @@ -4835,90 +4795,40 @@ } }, "node_modules/npm/node_modules/supports-color": { - "version": "9.4.0", + "version": "10.2.2", "dev": true, "inBundle": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/npm/node_modules/tar": { - "version": "6.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", + "version": "7.5.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/npm/node_modules/tar/node_modules/minipass": { + "node_modules/npm/node_modules/tar/node_modules/yallist": { "version": "5.0.0", "dev": true, "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/tar/node_modules/minizlib": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/tar/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=8" + "node": ">=18" } }, "node_modules/npm/node_modules/text-table": { @@ -4928,19 +4838,19 @@ "license": "MIT" }, "node_modules/npm/node_modules/tiny-relative-date": { - "version": "1.3.0", + "version": "2.0.2", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/tinyglobby": { - "version": "0.2.14", + "version": "0.2.15", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -4950,10 +4860,13 @@ } }, "node_modules/npm/node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.6", + "version": "6.5.0", "dev": true, "inBundle": true, "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -4964,7 +4877,7 @@ } }, "node_modules/npm/node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", + "version": "4.0.3", "dev": true, "inBundle": true, "license": "MIT", @@ -4986,30 +4899,17 @@ } }, "node_modules/npm/node_modules/tuf-js": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/models": "3.0.1", - "debug": "^4.3.6", - "make-fetch-happen": "^14.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/@tufjs/models": { - "version": "3.0.1", + "version": "4.0.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.5" + "@tufjs/models": "4.0.0", + "debug": "^4.4.1", + "make-fetch-happen": "^15.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/unique-filename": { @@ -5063,7 +4963,7 @@ } }, "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "6.0.1", + "version": "6.0.2", "dev": true, "inBundle": true, "license": "ISC", @@ -5072,10 +4972,13 @@ } }, "node_modules/npm/node_modules/walk-up-path": { - "version": "3.0.1", + "version": "4.0.0", "dev": true, "inBundle": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "20 || >=22" + } }, "node_modules/npm/node_modules/which": { "version": "5.0.0", @@ -5092,15 +4995,6 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/which/node_modules/isexe": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, "node_modules/npm/node_modules/wrap-ansi": { "version": "8.1.0", "dev": true, @@ -5152,7 +5046,7 @@ } }, "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", + "version": "6.2.2", "dev": true, "inBundle": true, "license": "MIT", @@ -5187,7 +5081,7 @@ } }, "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", + "version": "7.1.2", "dev": true, "inBundle": true, "license": "MIT", @@ -5516,27 +5410,6 @@ "dev": true, "license": "ISC" }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -5653,41 +5526,6 @@ "node": ">=8" } }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -5696,18 +5534,18 @@ "license": "MIT" }, "node_modules/semantic-release": { - "version": "24.2.9", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.9.tgz", - "integrity": "sha512-phCkJ6pjDi9ANdhuF5ElS10GGdAKY6R1Pvt9lT3SFhOwM4T7QZE7MLpBDbNruUx/Q3gFD92/UOFringGipRqZA==", + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-25.0.1.tgz", + "integrity": "sha512-0OCYLm0AfVilNGukM+w0C4aptITfuW1Mhvmz8LQliLeYbPOTFRCIJzoltWWx/F5zVFe6np9eNatBUHdAvMFeZg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@semantic-release/commit-analyzer": "^13.0.0-beta.1", + "@semantic-release/commit-analyzer": "^13.0.1", "@semantic-release/error": "^4.0.0", - "@semantic-release/github": "^11.0.0", - "@semantic-release/npm": "^12.0.2", - "@semantic-release/release-notes-generator": "^14.0.0-beta.1", + "@semantic-release/github": "^12.0.0", + "@semantic-release/npm": "^13.1.1", + "@semantic-release/release-notes-generator": "^14.1.0", "aggregate-error": "^5.0.0", "cosmiconfig": "^9.0.0", "debug": "^4.0.0", @@ -5718,7 +5556,7 @@ "get-stream": "^6.0.0", "git-log-parser": "^1.2.0", "hook-std": "^4.0.0", - "hosted-git-info": "^8.0.0", + "hosted-git-info": "^9.0.0", "import-from-esm": "^2.0.0", "lodash-es": "^4.17.21", "marked": "^15.0.0", @@ -5731,13 +5569,13 @@ "semver": "^7.3.2", "semver-diff": "^5.0.0", "signale": "^1.2.1", - "yargs": "^17.5.1" + "yargs": "^18.0.0" }, "bin": { "semantic-release": "bin/semantic-release.js" }, "engines": { - "node": ">=20.8.1" + "node": "^22.14.0 || >= 24.10.0" } }, "node_modules/semantic-release/node_modules/aggregate-error": { @@ -5787,16 +5625,16 @@ } }, "node_modules/semantic-release/node_modules/hosted-git-info": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", - "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.2.tgz", + "integrity": "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==", "dev": true, "license": "ISC", "dependencies": { - "lru-cache": "^10.0.1" + "lru-cache": "^11.1.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/semantic-release/node_modules/indent-string": { @@ -5812,6 +5650,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/semantic-release/node_modules/lru-cache": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/semantic-release/node_modules/p-reduce": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", @@ -6023,19 +5871,6 @@ "node": ">=8" } }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -6343,6 +6178,55 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6369,6 +6253,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, "node_modules/type-fest": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", @@ -6396,6 +6290,19 @@ "node": ">=0.8.0" } }, + "node_modules/undici": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/unicode-emoji-modifier-base": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", @@ -6542,32 +6449,72 @@ } }, "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^8.0.1", + "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", + "string-width": "^7.2.0", "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "yargs-parser": "^22.0.0" }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "dev": true, "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/yoctocolors": { diff --git a/package.json b/package.json index f39ed170..99f66d25 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,6 @@ "@semantic-release/release-notes-generator": "^14.0.3", "conventional-changelog-angular": "^8.0.0", "conventional-changelog-conventionalcommits": "^9.0.0", - "semantic-release": "^24.2.7" + "semantic-release": "^25.0.0" } } diff --git a/settings.gradle.kts b/settings.gradle.kts index f8e99441..f7e50c5f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,11 +19,12 @@ dependencyResolutionManagement { version("modrinth", "2.+") version("hangar", "0.1.3") version("paper.yml", "0.6.0") - version("paper.run", "3.0.1") + version("paper.run", "3.0.2") version("shadowJar", "9.2.2") version("paper", "1.21.8-R0.1-SNAPSHOT") version("bstats", "3.1.0") + version("customblockdata", "2.2.4") version("cloudcommand", "2.0.0") version("cloudcommandPaper", "2.0.0-SNAPSHOT") @@ -40,7 +41,7 @@ dependencyResolutionManagement { version("jakarta-inject", "2.0.1") // Testing dependencies - version("junit", "6.0.0") + version("junit", "6.0.1") version("mockito", "5.20.0") version("mockbukkit", "3.133.2") version("assertj", "3.27.6") @@ -69,9 +70,9 @@ dependencyResolutionManagement { library("paper", "io.papermc.paper", "paper-api").versionRef("paper") library("adventure.text.feature.pagination", "net.kyori", "adventure-text-feature-pagination").versionRef("adventure-text-feature-pagination") library("adventure.text.discord", "dev.vankka", "mcdiscordreserializer").versionRef("adventure-text-discord-serializer") - library("jda", "net.dv8tion", "JDA").versionRef("jda") library("jda-webhook", "club.minnced", "discord-webhooks").versionRef("jda-webhook") library("bstats", "org.bstats", "bstats-bukkit").versionRef("bstats") + library("customblockdata", "com.jeff-media", "custom-block-data").versionRef("customblockdata") library("cloud.command.paper", "org.incendo", "cloud-paper").versionRef("cloudcommandPaper") library("cloud.command.annotations", "org.incendo", "cloud-annotations").versionRef("cloudcommandAnnotations") diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/AntiRedstoneClockRemastered.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/AntiRedstoneClockRemastered.java index 802b6d55..56d3bfa6 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/AntiRedstoneClockRemastered.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/AntiRedstoneClockRemastered.java @@ -3,8 +3,10 @@ import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Stage; +import com.jeff_media.customblockdata.CustomBlockData; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; +import net.onelitefeather.antiredstoneclockremastered.api.PlotsquaredSupport; import net.onelitefeather.antiredstoneclockremastered.injection.MetricsModule; import net.onelitefeather.antiredstoneclockremastered.injection.CommandFrameworkModule; import net.onelitefeather.antiredstoneclockremastered.injection.CommandModule; @@ -14,10 +16,13 @@ import net.onelitefeather.antiredstoneclockremastered.injection.ServiceModule; import net.onelitefeather.antiredstoneclockremastered.injection.TranslationModule; import net.onelitefeather.antiredstoneclockremastered.service.UpdateService; +import net.onelitefeather.antiredstoneclockremastered.service.tracking.ConfigMode; import net.onelitefeather.antiredstoneclockremastered.utils.CheckTPS; +import org.bukkit.configuration.serialization.ConfigurationSerialization; import org.bukkit.plugin.java.JavaPlugin; import java.util.Arrays; +import java.util.Optional; public final class AntiRedstoneClockRemastered extends JavaPlugin { @@ -44,8 +49,12 @@ public void onLoad() { @Override public void onEnable() { + CustomBlockData.registerListener(this); injector.getInstance(TranslationModule.class); + var mode = ConfigMode.getEnum(getConfig(), "check.mode", ConfigMode.STATIC); + getComponentLogger().info(mode.getEnableMessage()); injector.getInstance(CheckTPS.class).startCheck(); + Optional.ofNullable(injector.getInstance(PlotsquaredSupport.class)).ifPresent(PlotsquaredSupport::init); donationInformation(); injector.getInstance(UpdateService.class).schedule(); injector.getInstance(UpdateService.class).run(); diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/DisplayActiveClocksCommand.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/DisplayActiveClocksCommand.java index fe6d52ff..3fc46e83 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/DisplayActiveClocksCommand.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/DisplayActiveClocksCommand.java @@ -1,15 +1,13 @@ package net.onelitefeather.antiredstoneclockremastered.commands; import jakarta.inject.Inject; +import jakarta.inject.Named; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TranslationArgument; -import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.feature.pagination.Pagination; import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; import net.onelitefeather.antiredstoneclockremastered.model.RedstoneClock; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneTrackingService; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; import org.incendo.cloud.annotation.specifier.Greedy; import org.incendo.cloud.annotations.Argument; import org.incendo.cloud.annotations.Command; @@ -30,13 +28,13 @@ */ public final class DisplayActiveClocksCommand implements Pagination.Renderer.RowRenderer { - private final RedstoneClockService redstoneClockService; + private final RedstoneTrackingService trackingService; private final Pagination.Builder pagination = Pagination.builder().resultsPerPage(4); @Inject - public DisplayActiveClocksCommand(RedstoneClockService redstoneClockService) { - this.redstoneClockService = redstoneClockService; + public DisplayActiveClocksCommand(RedstoneTrackingService trackingService) { + this.trackingService = trackingService; } @Command("arcm display [page]") @@ -50,7 +48,7 @@ public void displayClocks(CommandSender commandSender, @Greedy @Argument("page") if (page == null) { page = 0; } - build.render(this.redstoneClockService.getRedstoneClocks(), Math.max(1, page)) + build.render(this.trackingService.getRedstoneClocks(), Math.max(1, page)) .forEach(commandSender::sendMessage); } @@ -59,27 +57,9 @@ private String mapToCommand(int i) { return "/arcm display " + i; } - private Component mapClockToMessage(RedstoneClock redstoneClock) { - var location = redstoneClock.getLocation(); - return Component.empty().hoverEvent(Component.translatable("antiredstoneclockremastered.command.display.clock.hover").asHoverEvent()).append( - Component.translatable("antiredstoneclockremastered.command.display.clock.text") - .arguments( - TranslationArgument.numeric(redstoneClock.getTriggerCount()), - TranslationArgument.numeric(location.getBlockX()), - TranslationArgument.numeric(location.getBlockY()), - TranslationArgument.numeric(location.getBlockZ()), - Component.empty() - .clickEvent(ClickEvent.callback(audience -> { - if (audience instanceof final Player executor) { - executor.teleport(location); - } - })) - ) - ); - } - @Override public @NotNull Collection renderRow(@Nullable RedstoneClock redstoneClock, int index) { - return List.of(mapClockToMessage(redstoneClock)); + if (redstoneClock == null) return List.of(); + return List.of(redstoneClock.render()); } } diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/FeatureCommand.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/FeatureCommand.java index 86fea157..5cfec42a 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/FeatureCommand.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/FeatureCommand.java @@ -4,7 +4,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TranslationArgument; import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; +import net.onelitefeather.antiredstoneclockremastered.service.api.DecisionService; import org.bukkit.World; import org.bukkit.command.CommandSender; import org.incendo.cloud.annotations.Argument; @@ -25,12 +25,12 @@ public final class FeatureCommand { private final AntiRedstoneClockRemastered plugin; - private final RedstoneClockService redstoneClockService; + private final DecisionService decisionService; @Inject - public FeatureCommand(AntiRedstoneClockRemastered plugin, RedstoneClockService redstoneClockService) { + public FeatureCommand(AntiRedstoneClockRemastered plugin, DecisionService decisionService) { this.plugin = plugin; - this.redstoneClockService = redstoneClockService; + this.decisionService = decisionService; } @Command("check observer") @@ -39,7 +39,7 @@ public FeatureCommand(AntiRedstoneClockRemastered plugin, RedstoneClockService r public void toggleObserver(CommandSender sender) { plugin.getConfig().set("check.observer", !plugin.getConfig().getBoolean("check.observer")); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sendMessageToggleMessage(sender, plugin.getConfig().getBoolean("check.observer")); } @@ -49,7 +49,7 @@ public void toggleObserver(CommandSender sender) { public void togglePiston(CommandSender sender) { plugin.getConfig().set("check.piston", !plugin.getConfig().getBoolean("check.piston")); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sendMessageToggleMessage(sender, plugin.getConfig().getBoolean("check.piston")); } @@ -59,7 +59,7 @@ public void togglePiston(CommandSender sender) { public void toggleComparator(CommandSender sender) { plugin.getConfig().set("check.comparator", !plugin.getConfig().getBoolean("check.comparator")); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sendMessageToggleMessage(sender, plugin.getConfig().getBoolean("check.comparator")); } @@ -69,7 +69,7 @@ public void toggleComparator(CommandSender sender) { public void toggleSculk(CommandSender sender) { plugin.getConfig().set("check.sculk", !plugin.getConfig().getBoolean("check.sculk")); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sendMessageToggleMessage(sender, plugin.getConfig().getBoolean("check.sculk")); } @@ -79,7 +79,7 @@ public void toggleSculk(CommandSender sender) { public void toggleRedstoneAndRepeater(CommandSender sender) { plugin.getConfig().set("check.redstoneAndRepeater", !plugin.getConfig().getBoolean("check.redstoneAndRepeater")); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sendMessageToggleMessage(sender, plugin.getConfig().getBoolean("check.redstoneAndRepeater")); } @@ -99,7 +99,7 @@ public void addIgnoredWorld(CommandSender sender, @Argument("world") World world worlds.add(world.getName()); plugin.getConfig().set("check.ignoredWorlds", worlds); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sender.sendMessage(Component.translatable("antiredstoneclockremastered.command.feature.check.world.add").arguments(AntiRedstoneClockRemastered.PREFIX, Component.text(world.getName()))); } @@ -111,7 +111,7 @@ public void removeIgnoredWorld(CommandSender sender, @Argument("world") World wo worlds.remove(world.getName()); plugin.getConfig().set("check.ignoredWorlds", worlds); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sender.sendMessage(Component.translatable("antiredstoneclockremastered.command.feature.check.world.remove").arguments(AntiRedstoneClockRemastered.PREFIX, Component.text(world.getName()))); } @@ -123,7 +123,7 @@ public void addIgnoredRegion(CommandSender sender, @Argument("region") String re regions.add(region); plugin.getConfig().set("check.ignoredRegions", regions); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sender.sendMessage(Component.translatable("antiredstoneclockremastered.command.feature.check.region.add").arguments(AntiRedstoneClockRemastered.PREFIX, Component.text(region))); } @@ -135,7 +135,7 @@ public void removeIgnoredRegion(CommandSender sender, @Argument("region") String regions.remove(region); plugin.getConfig().set("check.ignoredRegions", regions); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sender.sendMessage(Component.translatable("antiredstoneclockremastered.command.feature.check.region.remove").arguments(AntiRedstoneClockRemastered.PREFIX, Component.text(region))); } @@ -145,7 +145,7 @@ public void removeIgnoredRegion(CommandSender sender, @Argument("region") String public void toggleAutoBreak(CommandSender sender) { plugin.getConfig().set("clock.autoBreak", !plugin.getConfig().getBoolean("clock.autoBreak")); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sendMessageToggleMessage(sender, plugin.getConfig().getBoolean("clock.autoBreak")); } @@ -155,7 +155,7 @@ public void toggleAutoBreak(CommandSender sender) { public void toggleNotifyAdmins(CommandSender sender) { plugin.getConfig().set("clock.notifyAdmins", !plugin.getConfig().getBoolean("clock.notifyAdmins")); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sendMessageToggleMessage(sender, plugin.getConfig().getBoolean("clock.notifyAdmins")); } @@ -165,7 +165,7 @@ public void toggleNotifyAdmins(CommandSender sender) { public void toggleNotifyConsole(CommandSender sender) { plugin.getConfig().set("clock.notifyConsole", !plugin.getConfig().getBoolean("clock.notifyConsole")); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sendMessageToggleMessage(sender, plugin.getConfig().getBoolean("clock.notifyConsole")); } @@ -175,7 +175,7 @@ public void toggleNotifyConsole(CommandSender sender) { public void toggleDrop(CommandSender sender) { plugin.getConfig().set("clock.drop", !plugin.getConfig().getBoolean("clock.drop")); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sendMessageToggleMessage(sender, plugin.getConfig().getBoolean("clock.drop")); } @@ -185,7 +185,7 @@ public void toggleDrop(CommandSender sender) { public void setEndDelay(CommandSender sender,@Argument("delay") Integer endDeplay) { plugin.getConfig().set("clock.endDelay", endDeplay); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sendMessageSetMessage(sender, plugin.getConfig().getInt("clock.endDelay")); } @@ -195,7 +195,7 @@ public void setEndDelay(CommandSender sender,@Argument("delay") Integer endDepla public void setMaxCount(CommandSender sender,@Argument("count") Integer count) { plugin.getConfig().set("clock.maxCount", count); plugin.saveConfig(); - redstoneClockService.reload(); + decisionService.reload(); sendMessageSetMessage(sender, plugin.getConfig().getInt("clock.maxCount")); } diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/ReloadCommand.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/ReloadCommand.java index 413e3de2..362bfdfa 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/ReloadCommand.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/commands/ReloadCommand.java @@ -3,7 +3,7 @@ import jakarta.inject.Inject; import net.kyori.adventure.text.Component; import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; +import net.onelitefeather.antiredstoneclockremastered.service.api.DecisionService; import org.bukkit.command.CommandSender; import org.incendo.cloud.annotations.Command; import org.incendo.cloud.annotations.CommandDescription; @@ -18,18 +18,18 @@ */ public final class ReloadCommand { - private final RedstoneClockService redstoneClockService; + private final DecisionService decisionService; @Inject - public ReloadCommand(RedstoneClockService redstoneClockService) { - this.redstoneClockService = redstoneClockService; + public ReloadCommand(DecisionService decisionService) { + this.decisionService = decisionService; } @Command("arcm reload") @CommandDescription("antiredstoneclockremastered.command.reload.description") @Permission("antiredstoneclockremastered.command.reload") public void reloadConfig(CommandSender commandSender) { - this.redstoneClockService.reload(); + this.decisionService.reload(); commandSender.sendMessage(Component.translatable("antiredstoneclockremastered.command.reload.success").arguments(AntiRedstoneClockRemastered.PREFIX)); } } diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ExternalSupportModule.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ExternalSupportModule.java index 65f2e5f3..547a7c44 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ExternalSupportModule.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ExternalSupportModule.java @@ -88,8 +88,6 @@ public PlotsquaredSupport providePlotsquaredSupport(AntiRedstoneClockRemastered LOGGER.info("Thanks to hold your software up-to date <3"); support = new PlotSquaredModernSupport(); } - - support.init(); return support; } } \ No newline at end of file diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ListenerModule.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ListenerModule.java index e1770196..70d116f9 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ListenerModule.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ListenerModule.java @@ -2,10 +2,8 @@ import com.google.inject.AbstractModule; import com.google.inject.Injector; -import com.google.inject.Provides; import net.onelitefeather.antiredstoneclockremastered.listener.*; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; -import net.onelitefeather.antiredstoneclockremastered.utils.CheckTPS; +import net.onelitefeather.antiredstoneclockremastered.service.api.DecisionService; import org.bukkit.Material; import org.bukkit.plugin.Plugin; @@ -29,63 +27,49 @@ protected void configure() { /** * Creates ComparatorListener instances for different materials. */ - private ComparatorListener createComparatorListener(Material material, RedstoneClockService redstoneClockService, - CheckTPS checkTPS, Plugin plugin) { - return new ComparatorListener(material, redstoneClockService, checkTPS, plugin); + private ComparatorListener createComparatorListener(Material material, DecisionService decisionService) { + return new ComparatorListener(material, decisionService); } /** * Creates RedstoneListener instances for different materials. */ - private RedstoneListener createRedstoneListener(Material material, RedstoneClockService redstoneClockService, - CheckTPS checkTPS, Plugin plugin) { - return new RedstoneListener(material, redstoneClockService, checkTPS, plugin); + private RedstoneListener createRedstoneListener(Material material, DecisionService decisionService) { + return new RedstoneListener(material, decisionService); } public void registerEvents(Injector injector, Plugin plugin) { // Register DI-enabled listeners plugin.getServer().getPluginManager().registerEvents(injector.getInstance(PlayerListener.class), plugin); + plugin.getServer().getPluginManager().registerEvents(injector.getInstance(ObserverListener.class), plugin); - if (plugin.getConfig().getBoolean("check.observer", true)) { - plugin.getServer().getPluginManager().registerEvents(injector.getInstance(ObserverListener.class), plugin); - } - - if (plugin.getConfig().getBoolean("check.sculk", true)) { - var sculk = Material.getMaterial("SCULK"); - if (sculk != null) { - plugin.getServer().getPluginManager().registerEvents(injector.getInstance(SculkListener.class), plugin); - } - } - - if (plugin.getConfig().getBoolean("check.piston", true)) { - plugin.getServer().getPluginManager().registerEvents(injector.getInstance(PistonListener.class), plugin); + var sculk = Material.getMaterial("SCULK"); + if (sculk != null) { + plugin.getServer().getPluginManager().registerEvents(injector.getInstance(SculkListener.class), plugin); } + plugin.getServer().getPluginManager().registerEvents(injector.getInstance(PistonListener.class), plugin); // Material-dependent listeners now use dependency injection - if (plugin.getConfig().getBoolean("check.comparator", true)) { - var comparator = Material.getMaterial("COMPARATOR"); - if (comparator != null) { - var listener = createComparatorListener(comparator, injector.getInstance(RedstoneClockService.class), injector.getInstance(CheckTPS.class), plugin); - plugin.getServer().getPluginManager().registerEvents(listener, plugin); - } else { - var listener1 = createComparatorListener(Material.getMaterial("REDSTONE_COMPARATOR_OFF"), injector.getInstance(RedstoneClockService.class), injector.getInstance(CheckTPS.class), plugin); - var listener2 = createComparatorListener(Material.getMaterial("REDSTONE_COMPARATOR_ON"), injector.getInstance(RedstoneClockService.class), injector.getInstance(CheckTPS.class), plugin); - plugin.getServer().getPluginManager().registerEvents(listener1, plugin); - plugin.getServer().getPluginManager().registerEvents(listener2, plugin); - } + var comparator = Material.getMaterial("COMPARATOR"); + if (comparator != null) { + var listener = createComparatorListener(comparator, injector.getInstance(DecisionService.class)); + plugin.getServer().getPluginManager().registerEvents(listener, plugin); + } else { + var listener1 = createComparatorListener(Material.getMaterial("REDSTONE_COMPARATOR_OFF"), injector.getInstance(DecisionService.class)); + var listener2 = createComparatorListener(Material.getMaterial("REDSTONE_COMPARATOR_ON"), injector.getInstance(DecisionService.class)); + plugin.getServer().getPluginManager().registerEvents(listener1, plugin); + plugin.getServer().getPluginManager().registerEvents(listener2, plugin); } - if (plugin.getConfig().getBoolean("check.redstoneAndRepeater", true)) { - var repeater = Material.getMaterial("REPEATER"); - if (repeater != null) { - var listener = createRedstoneListener(repeater, injector.getInstance(RedstoneClockService.class), injector.getInstance(CheckTPS.class), plugin); - plugin.getServer().getPluginManager().registerEvents(listener, plugin); - } else { - var listener1 = createRedstoneListener(Material.getMaterial("DIODE_BLOCK_ON"), injector.getInstance(RedstoneClockService.class), injector.getInstance(CheckTPS.class), plugin); - var listener2 = createRedstoneListener(Material.getMaterial("DIODE_BLOCK_OFF"), injector.getInstance(RedstoneClockService.class), injector.getInstance(CheckTPS.class), plugin); - plugin.getServer().getPluginManager().registerEvents(listener1, plugin); - plugin.getServer().getPluginManager().registerEvents(listener2, plugin); - } + var repeater = Material.getMaterial("REPEATER"); + if (repeater != null) { + var listener = createRedstoneListener(repeater, injector.getInstance(DecisionService.class)); + plugin.getServer().getPluginManager().registerEvents(listener, plugin); + } else { + var listener1 = createRedstoneListener(Material.getMaterial("DIODE_BLOCK_ON"), injector.getInstance(DecisionService.class)); + var listener2 = createRedstoneListener(Material.getMaterial("DIODE_BLOCK_OFF"), injector.getInstance(DecisionService.class)); + plugin.getServer().getPluginManager().registerEvents(listener1, plugin); + plugin.getServer().getPluginManager().registerEvents(listener2, plugin); } } } \ No newline at end of file diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ServiceModule.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ServiceModule.java index e0bc98f1..abc68542 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ServiceModule.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/ServiceModule.java @@ -1,19 +1,22 @@ package net.onelitefeather.antiredstoneclockremastered.injection; import com.google.inject.AbstractModule; +import com.google.inject.Injector; import com.google.inject.Provides; import com.google.inject.Singleton; -import io.papermc.paper.ServerBuildInfo; +import jakarta.inject.Named; import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; -import net.onelitefeather.antiredstoneclockremastered.api.PlotsquaredSupport; -import net.onelitefeather.antiredstoneclockremastered.api.WorldGuardSupport; -import net.onelitefeather.antiredstoneclockremastered.service.api.NotificationService; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; -import net.onelitefeather.antiredstoneclockremastered.service.api.RegionService; -import net.onelitefeather.antiredstoneclockremastered.service.factory.RedstoneClockServiceFactory; +import net.onelitefeather.antiredstoneclockremastered.service.api.*; +import net.onelitefeather.antiredstoneclockremastered.service.chain.*; +import net.onelitefeather.antiredstoneclockremastered.service.factory.DecisionServiceFactory; import net.onelitefeather.antiredstoneclockremastered.service.UpdateService; -import net.onelitefeather.antiredstoneclockremastered.service.api.TranslationService; -import net.onelitefeather.antiredstoneclockremastered.service.impl.*; +import net.onelitefeather.antiredstoneclockremastered.service.notification.AdminNotificationService; +import net.onelitefeather.antiredstoneclockremastered.service.notification.ConsoleNotificationService; +import net.onelitefeather.antiredstoneclockremastered.service.notification.DiscordNotificationService; +import net.onelitefeather.antiredstoneclockremastered.service.notification.SignNotificationService; +import net.onelitefeather.antiredstoneclockremastered.service.tracking.DelegatedTrackingService; +import net.onelitefeather.antiredstoneclockremastered.service.tracking.DynamicTrackingService; +import net.onelitefeather.antiredstoneclockremastered.service.tracking.StaticTrackingService; import net.onelitefeather.antiredstoneclockremastered.utils.CheckTPS; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,17 +38,6 @@ protected void configure() { bind(CheckTPS.class).in(Singleton.class); } - @Provides - @Singleton - public RedstoneClockService provideRedstoneClockService(AntiRedstoneClockRemastered plugin, - RegionService regionService, - PlotsquaredSupport plotsquaredSupport, - WorldGuardSupport worldGuardSupport, - NotificationService notificationService) { - return RedstoneClockServiceFactory.createService(plugin, regionService, plotsquaredSupport, worldGuardSupport, - notificationService); - } - @Provides @Singleton public NotificationService providesNotificationService(AntiRedstoneClockRemastered antiRedstoneClockRemastered, @@ -57,4 +49,45 @@ public NotificationService providesNotificationService(AntiRedstoneClockRemaster return discordNotification; } + @Provides + @Named("staticTrackingService") + @Singleton + public RedstoneTrackingService providesStaticTrackingService(Injector injector) { + return injector.getInstance(StaticTrackingService.class); + } + + @Provides + @Named("dynamicTrackingService") + public RedstoneTrackingService providesDynamicTrackingService(Injector injector) { + return injector.getInstance(DynamicTrackingService.class); + } + + @Provides + @Singleton + public RedstoneTrackingService providesDelegatedTrackingService(Injector injector) { + return injector.getInstance(DelegatedTrackingService.class); + } + + @Provides + @Singleton + public RedstoneClockMiddleware provideRedstoneClockMiddleware(Injector injector) { + return RedstoneClockMiddleware.link( + injector.getInstance(TPSRedstoneClockMiddleware.class), + injector.getInstance(SkipEventTypeRedstoneClockMiddleware.class), + injector.getInstance(WorldRedstoneClockMiddleware.class), + injector.getInstance(WorldGuardRedstoneClockMiddleware.class), + injector.getInstance(PlotSquaredRedstoneClockMiddleware.class), + injector.getInstance(TrackingRedstoneClockMiddleware.class) + ); + } + + @Provides + @Singleton + public DecisionService provideDecisionService(AntiRedstoneClockRemastered plugin, + RegionService regionService, + RedstoneClockMiddleware middleware, + NotificationService notificationService) { + return DecisionServiceFactory.createService(plugin, regionService, middleware, notificationService); + } + } \ No newline at end of file diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/TranslationModule.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/TranslationModule.java index fde1e044..9b4439e9 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/TranslationModule.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/injection/TranslationModule.java @@ -8,8 +8,8 @@ import net.kyori.adventure.util.UTF8ResourceBundleControl; import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; import net.onelitefeather.antiredstoneclockremastered.service.api.TranslationService; -import net.onelitefeather.antiredstoneclockremastered.service.impl.LegacyTranslationService; -import net.onelitefeather.antiredstoneclockremastered.service.impl.ModernTranslationService; +import net.onelitefeather.antiredstoneclockremastered.service.translation.LegacyTranslationService; +import net.onelitefeather.antiredstoneclockremastered.service.translation.ModernTranslationService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/ComparatorListener.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/ComparatorListener.java index ed40124f..8e7c564a 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/ComparatorListener.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/ComparatorListener.java @@ -1,14 +1,12 @@ package net.onelitefeather.antiredstoneclockremastered.listener; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; -import net.onelitefeather.antiredstoneclockremastered.utils.CheckTPS; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import net.onelitefeather.antiredstoneclockremastered.service.api.DecisionService; import org.bukkit.Material; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockRedstoneEvent; -import org.bukkit.plugin.Plugin; /** * Listener for handling comparator-based redstone clocks. @@ -20,30 +18,21 @@ */ public final class ComparatorListener implements Listener { private final Material comparatorMaterial; - private final RedstoneClockService redstoneClockService; - private final CheckTPS checkTPS; - private final FileConfiguration config; + private final DecisionService decisionService; - public ComparatorListener(Material comparatorMaterial, RedstoneClockService redstoneClockService, - CheckTPS checkTPS, Plugin plugin) { + public ComparatorListener(Material comparatorMaterial, DecisionService decisionService) { this.comparatorMaterial = comparatorMaterial; - this.redstoneClockService = redstoneClockService; - this.checkTPS = checkTPS; - this.config = plugin.getConfig(); + this.decisionService = decisionService; } @EventHandler(priority = EventPriority.LOWEST) private void onRedstoneComparatorClock(BlockRedstoneEvent blockRedstoneEvent) { - - if (!this.checkTPS.isTpsOk()) return; - if (!this.config.getBoolean("check.comparator")) return; - var block = blockRedstoneEvent.getBlock(); var type = block.getType(); if (type != comparatorMaterial) return; if (blockRedstoneEvent.getOldCurrent() != 0) return; - this.redstoneClockService.checkAndUpdateClockState(block); + this.decisionService.makeDecisionWithContext(RedstoneClockMiddleware.CheckContext.of(block, RedstoneClockMiddleware.EventType.COMPARATOR)); } } diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/ObserverListener.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/ObserverListener.java index bf7edb7d..a00ad30a 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/ObserverListener.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/ObserverListener.java @@ -1,9 +1,8 @@ package net.onelitefeather.antiredstoneclockremastered.listener; import jakarta.inject.Inject; -import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; -import net.onelitefeather.antiredstoneclockremastered.utils.CheckTPS; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import net.onelitefeather.antiredstoneclockremastered.service.api.DecisionService; import org.bukkit.Material; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -12,30 +11,24 @@ public final class ObserverListener implements Listener { private final Material material; - private final AntiRedstoneClockRemastered plugin; - private final CheckTPS checkTPS; - private final RedstoneClockService redstoneClockService; + private final DecisionService decisionService; @Inject - public ObserverListener(AntiRedstoneClockRemastered plugin, CheckTPS checkTPS, RedstoneClockService redstoneClockService) { + public ObserverListener(DecisionService decisionService) { this.material = Material.OBSERVER; - this.plugin = plugin; - this.checkTPS = checkTPS; - this.redstoneClockService = redstoneClockService; + this.decisionService = decisionService; } @EventHandler(priority = EventPriority.LOWEST) private void onRedstoneObserverClock(BlockRedstoneEvent blockRedstoneEvent) { - if (!this.checkTPS.isTpsOk()) return; - if (!this.plugin.getConfig().getBoolean("check.observer")) return; - var block = blockRedstoneEvent.getBlock(); var type = block.getType(); if (type != material) return; - if (blockRedstoneEvent.getOldCurrent() != 0) return; - this.redstoneClockService.checkAndUpdateClockStateWithActive(block); + + this.decisionService.makeDecisionWithContext( + RedstoneClockMiddleware.CheckContext.of(block, true, RedstoneClockMiddleware.EventType.OBSERVER)); } } diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/PistonListener.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/PistonListener.java index ac2c2993..325d82a5 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/PistonListener.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/PistonListener.java @@ -1,47 +1,31 @@ package net.onelitefeather.antiredstoneclockremastered.listener; import jakarta.inject.Inject; -import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; -import net.onelitefeather.antiredstoneclockremastered.utils.CheckTPS; -import org.bukkit.Material; +import net.onelitefeather.antiredstoneclockremastered.service.api.DecisionService; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPistonExtendEvent; import org.bukkit.event.block.BlockPistonRetractEvent; -import org.bukkit.event.block.BlockRedstoneEvent; public final class PistonListener implements Listener { - private final AntiRedstoneClockRemastered plugin; - private final CheckTPS checkTPS; - private final RedstoneClockService redstoneClockService; + private final DecisionService decisionService; @Inject - public PistonListener(AntiRedstoneClockRemastered plugin, CheckTPS checkTPS, RedstoneClockService redstoneClockService) { - this.plugin = plugin; - this.checkTPS = checkTPS; - this.redstoneClockService = redstoneClockService; + public PistonListener(DecisionService decisionService) { + this.decisionService = decisionService; } @EventHandler(priority = EventPriority.LOWEST) private void onPistonExtendEvent(BlockPistonExtendEvent blockPistonExtendEvent) { - - if (!this.checkTPS.isTpsOk()) return; - if (!this.plugin.getConfig().getBoolean("check.piston")) return; - var block = blockPistonExtendEvent.getBlock(); - - this.redstoneClockService.checkAndUpdateClockStateWithActiveManual(block, false); + this.decisionService.makeDecisionWithContext(RedstoneClockMiddleware.CheckContext.of(block, false, RedstoneClockMiddleware.EventType.PISTON)); } @EventHandler(priority = EventPriority.LOWEST) private void onPistonRetractEvent(BlockPistonRetractEvent blockPistonExtendEvent) { - if (!this.checkTPS.isTpsOk()) return; - if (!this.plugin.getConfig().getBoolean("check.piston")) return; - var block = blockPistonExtendEvent.getBlock(); - - this.redstoneClockService.checkAndUpdateClockStateWithActiveManual(block, true); + this.decisionService.makeDecisionWithContext(RedstoneClockMiddleware.CheckContext.of(block, true, RedstoneClockMiddleware.EventType.PISTON)); } } diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/PlayerListener.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/PlayerListener.java index bdd095a9..f6bca7bd 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/PlayerListener.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/PlayerListener.java @@ -1,10 +1,11 @@ package net.onelitefeather.antiredstoneclockremastered.listener; import jakarta.inject.Inject; +import jakarta.inject.Named; import net.kyori.adventure.text.Component; import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; import net.onelitefeather.antiredstoneclockremastered.service.UpdateService; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneTrackingService; import net.onelitefeather.antiredstoneclockremastered.utils.Constants; import org.bukkit.block.BlockFace; import org.bukkit.event.EventHandler; @@ -15,12 +16,12 @@ public final class PlayerListener implements Listener { - private final RedstoneClockService redstoneClockService; + private final RedstoneTrackingService trackingService; private final UpdateService updateService; @Inject - public PlayerListener(RedstoneClockService redstoneClockService, UpdateService updateService) { - this.redstoneClockService = redstoneClockService; + public PlayerListener(RedstoneTrackingService trackingService, UpdateService updateService) { + this.trackingService = trackingService; this.updateService = updateService; } @@ -40,7 +41,7 @@ private void onBlockBreak(BlockBreakEvent blockBreakEvent) { var block = blockBreakEvent.getBlock(); recheck: if (Constants.REDSTONE_ITEMS.contains(block.getType())) { - this.redstoneClockService.removeClockByLocation(block.getLocation()); + this.trackingService.removeClockByLocation(block.getLocation()); } else { block = block.getRelative(BlockFace.UP); break recheck; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/RedstoneListener.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/RedstoneListener.java index b0719054..5d304dc5 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/RedstoneListener.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/RedstoneListener.java @@ -1,14 +1,12 @@ package net.onelitefeather.antiredstoneclockremastered.listener; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; -import net.onelitefeather.antiredstoneclockremastered.utils.CheckTPS; +import net.onelitefeather.antiredstoneclockremastered.service.api.DecisionService; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; import org.bukkit.Material; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockRedstoneEvent; -import org.bukkit.plugin.Plugin; /** * Listener for handling redstone repeater-based redstone clocks. @@ -20,30 +18,20 @@ */ public final class RedstoneListener implements Listener { private final Material repeaterMaterial; - private final RedstoneClockService redstoneClockService; - private final CheckTPS checkTPS; - private final FileConfiguration config; + private final DecisionService decisionService; - public RedstoneListener(Material repeaterMaterial, RedstoneClockService redstoneClockService, - CheckTPS checkTPS, Plugin plugin) { + public RedstoneListener(Material repeaterMaterial, DecisionService decisionService) { this.repeaterMaterial = repeaterMaterial; - this.redstoneClockService = redstoneClockService; - this.checkTPS = checkTPS; - this.config = plugin.getConfig(); + this.decisionService = decisionService; } @EventHandler(priority = EventPriority.LOWEST) private void onRedstoneClock(BlockRedstoneEvent blockRedstoneEvent) { - - if (!this.checkTPS.isTpsOk()) return; - if (!this.config.getBoolean("check.redstoneAndRepeater")) return; - var block = blockRedstoneEvent.getBlock(); var type = block.getType(); if (type != Material.REDSTONE_WIRE && type != repeaterMaterial) return; - if (blockRedstoneEvent.getOldCurrent() != 0) return; - - this.redstoneClockService.checkAndUpdateClockState(block); + this.decisionService.makeDecisionWithContext( + RedstoneClockMiddleware.CheckContext.of(block, RedstoneClockMiddleware.EventType.REDSTONE_AND_REPEATER)); } } diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/SculkListener.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/SculkListener.java index 61e3a5da..88d24b94 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/SculkListener.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/listener/SculkListener.java @@ -1,9 +1,8 @@ package net.onelitefeather.antiredstoneclockremastered.listener; import jakarta.inject.Inject; -import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; -import net.onelitefeather.antiredstoneclockremastered.utils.CheckTPS; +import net.onelitefeather.antiredstoneclockremastered.service.api.DecisionService; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -11,23 +10,18 @@ public final class SculkListener implements Listener { - private final AntiRedstoneClockRemastered plugin; - private final CheckTPS checkTPS; - private final RedstoneClockService redstoneClockService; + private final DecisionService decisionService; @Inject - public SculkListener(AntiRedstoneClockRemastered plugin, CheckTPS checkTPS, RedstoneClockService redstoneClockService) { - this.plugin = plugin; - this.checkTPS = checkTPS; - this.redstoneClockService = redstoneClockService; + public SculkListener(DecisionService decisionService) { + this.decisionService = decisionService; } @EventHandler(priority = EventPriority.LOWEST) private void onBlockReceiveGameEvent(BlockReceiveGameEvent event) { - if (!this.checkTPS.isTpsOk()) return; - if (!this.plugin.getConfig().getBoolean("check.sculk")) return; var block = event.getBlock(); - this.redstoneClockService.checkAndUpdateClockState(block); + this.decisionService.makeDecisionWithContext( + RedstoneClockMiddleware.CheckContext.of(block, RedstoneClockMiddleware.EventType.SCULK_SENSOR)); } } diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/model/DynamicRedstoneClock.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/model/DynamicRedstoneClock.java new file mode 100644 index 00000000..d051ec60 --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/model/DynamicRedstoneClock.java @@ -0,0 +1,99 @@ +package net.onelitefeather.antiredstoneclockremastered.model; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TranslationArgument; +import net.kyori.adventure.text.event.ClickEvent; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class DynamicRedstoneClock implements RedstoneClock { + + /** + * How often the clocks gets triggered + */ + private int triggerCount = 0; + + /** + * Shows if the piston/observer extended/enabled + */ + private boolean active; + private boolean detected; + + /** + * Where's the clock located + */ + private Location currentLocation; + private final long endTime; + private final UUID uuid; + + public DynamicRedstoneClock(@NotNull Location currentLocation, long endTime) { + this.currentLocation = currentLocation; + this.endTime = endTime; + this.uuid = UUID.randomUUID(); + } + + public void incrementTriggerCount() { + this.triggerCount++; + } + + public int getTriggerCount() { + return triggerCount; + } + + public void setActive(boolean active) { + this.active = active; + } + + public boolean isActive() { + return active; + } + + public boolean isDetected() { + return detected; + } + + public void setDetected(boolean detected) { + this.detected = detected; + } + + public boolean isTimeOut() { + return (System.currentTimeMillis() / 1000) >= endTime; + } + + @NotNull + public Location getCurrentLocation() { + return currentLocation; + } + + public void setCurrentLocation(@NotNull Location currentLocation) { + this.currentLocation = currentLocation; + } + + public UUID getUuid() { + return uuid; + } + + + + @Override + public Component render() { + var location = getCurrentLocation(); + return Component.empty().hoverEvent(Component.translatable("antiredstoneclockremastered.command.display.clock.hover").asHoverEvent()).append( + Component.translatable("antiredstoneclockremastered.command.display.clock.text") + .arguments( + TranslationArgument.numeric(getTriggerCount()), + TranslationArgument.numeric(location.getBlockX()), + TranslationArgument.numeric(location.getBlockY()), + TranslationArgument.numeric(location.getBlockZ()), + Component.empty() + ).clickEvent(ClickEvent.callback(audience -> { + if (audience instanceof final Player executor) { + executor.teleport(location); + } + })) + ); + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/model/RedstoneClock.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/model/RedstoneClock.java index 4d64b0a3..7e9eee05 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/model/RedstoneClock.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/model/RedstoneClock.java @@ -1,62 +1,15 @@ package net.onelitefeather.antiredstoneclockremastered.model; -import org.bukkit.Location; -import org.jetbrains.annotations.NotNull; +import net.kyori.adventure.text.Component; -public final class RedstoneClock { +/** + * Redstone Clock interface. + * @author TheMeinerLP + * @version 1.0.0 + * @since 2.5.0 + */ +public interface RedstoneClock { - /** - * How often the clocks gets triggered - */ - private int triggerCount = 0; + Component render(); - /** - * Shows if the piston/observer extended/enabled - */ - private boolean active; - private boolean detected; - - /** - * Where's the clock located - */ - private final @NotNull Location location; - private final long endTime; - - public RedstoneClock(@NotNull Location location, long endTime) { - this.location = location; - this.endTime = endTime; - } - - public void incrementTriggerCount() { - this.triggerCount++; - } - - public int getTriggerCount() { - return triggerCount; - } - - public void setActive(boolean active) { - this.active = active; - } - - public boolean isActive() { - return active; - } - - public boolean isDetected() { - return detected; - } - - public void setDetected(boolean detected) { - this.detected = detected; - } - - public boolean isTimeOut() { - return (System.currentTimeMillis() / 1000) >= endTime; - } - - @NotNull - public Location getLocation() { - return location; - } } diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/model/StaticRedstoneClock.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/model/StaticRedstoneClock.java new file mode 100644 index 00000000..699e29b8 --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/model/StaticRedstoneClock.java @@ -0,0 +1,85 @@ +package net.onelitefeather.antiredstoneclockremastered.model; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TranslationArgument; +import net.kyori.adventure.text.event.ClickEvent; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public final class StaticRedstoneClock implements RedstoneClock { + + /** + * How often the clocks gets triggered + */ + private int triggerCount = 0; + + /** + * Shows if the piston/observer extended/enabled + */ + private boolean active; + private boolean detected; + + /** + * Where's the clock located + */ + private final @NotNull Location location; + private final long endTime; + + public StaticRedstoneClock(@NotNull Location location, long endTime) { + this.location = location; + this.endTime = endTime; + } + + public void incrementTriggerCount() { + this.triggerCount++; + } + + public int getTriggerCount() { + return triggerCount; + } + + public void setActive(boolean active) { + this.active = active; + } + + public boolean isActive() { + return active; + } + + public boolean isDetected() { + return detected; + } + + public void setDetected(boolean detected) { + this.detected = detected; + } + + public boolean isTimeOut() { + return (System.currentTimeMillis() / 1000) >= endTime; + } + + @NotNull + public Location getLocation() { + return location; + } + + @Override + public Component render() { + var location = getLocation(); + return Component.empty().hoverEvent(Component.translatable("antiredstoneclockremastered.command.display.clock.hover").asHoverEvent()).append( + Component.translatable("antiredstoneclockremastered.command.display.clock.text") + .arguments( + TranslationArgument.numeric(getTriggerCount()), + TranslationArgument.numeric(location.getBlockX()), + TranslationArgument.numeric(location.getBlockY()), + TranslationArgument.numeric(location.getBlockZ()), + Component.empty() + ).clickEvent(ClickEvent.callback(audience -> { + if (audience instanceof final Player executor) { + executor.teleport(location); + } + })) + ); + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/DecisionService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/DecisionService.java new file mode 100644 index 00000000..b0cf6cbe --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/DecisionService.java @@ -0,0 +1,23 @@ +package net.onelitefeather.antiredstoneclockremastered.service.api; + +/** + * Service interface for managing redstone clock detection and handling. + * This abstraction allows for different implementations (e.g., Bukkit, Folia). + * + * @author TheMeinerLP + * @version 2.3.0 + * @since 1.0.0 + */ +public interface DecisionService { + + /** + * Check the state of the clock at the specified block. + * @param context the check context + */ + void makeDecisionWithContext(RedstoneClockMiddleware.CheckContext context); + + /** + * Reload the service configuration. + */ + void reload(); +} \ No newline at end of file diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/RedstoneClockMiddleware.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/RedstoneClockMiddleware.java new file mode 100644 index 00000000..98e3a1c4 --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/RedstoneClockMiddleware.java @@ -0,0 +1,54 @@ +package net.onelitefeather.antiredstoneclockremastered.service.api; + +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.jetbrains.annotations.Nullable; + +public abstract class RedstoneClockMiddleware { + + private RedstoneClockMiddleware next; + + public static RedstoneClockMiddleware link(RedstoneClockMiddleware first, RedstoneClockMiddleware... chain) { + var head = first; + for (var nextInChain : chain) { + head.next = nextInChain; + head = nextInChain; + } + return first; + } + + public abstract ResultState check(CheckContext context); + + protected ResultState checkNext(CheckContext checkContext) { + return this.next.check(checkContext); + } + + public enum ResultState { + REMOVE_AND_DROP, + REMOVE_AND_WITHOUT_DROP, + ONLY_NOTIFY, + SKIP + } + + public enum EventType { + PISTON, + REDSTONE_AND_REPEATER, + SCULK_SENSOR, + COMPARATOR, + OBSERVER, + } + + public record CheckContext(Location location, Block block, @Nullable Boolean state, EventType eventType) { + public static CheckContext of(Location location, Block block, @Nullable Boolean state, EventType eventType) { + return new CheckContext(location, block, state, eventType); + } + + public static CheckContext of(Block block, @Nullable Boolean state, EventType eventType) { + return new CheckContext(block.getLocation(), block, state, eventType); + } + + public static CheckContext of(Block block, EventType eventType) { + return new CheckContext(block.getLocation(), block, null, eventType); + } + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/RedstoneClockService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/RedstoneClockService.java deleted file mode 100644 index ca79c082..00000000 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/RedstoneClockService.java +++ /dev/null @@ -1,128 +0,0 @@ -package net.onelitefeather.antiredstoneclockremastered.service.api; - -import net.onelitefeather.antiredstoneclockremastered.model.RedstoneClock; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.Map; - -/** - * Service interface for managing redstone clock detection and handling. - * This abstraction allows for different implementations (e.g., Bukkit, Folia). - * - * @author TheMeinerLP - * @version 2.2.0 - * @since 1.0.0 - */ -public interface RedstoneClockService { - - /** - * Check and update clock state with manual active state control. - * - * @param location the location to check - * @param state the active state to set - */ - void checkAndUpdateClockStateWithActiveManual(Location location, boolean state); - - /** - * Check and update clock state with manual active state control. - * - * @param block the block to check - * @param state the active state to set - */ - void checkAndUpdateClockStateWithActiveManual(Block block, boolean state); - - /** - * Check and update clock state with automatic active state detection. - * - * @param block the block to check - */ - void checkAndUpdateClockStateWithActive(Block block); - - /** - * Check and update clock state with automatic active state detection. - * - * @param location the location to check - */ - void checkAndUpdateClockStateWithActive(Location location); - - /** - * Check and update clock state without active state management. - * - * @param block the block to check - */ - void checkAndUpdateClockState(Block block); - - /** - * Check and update clock state without active state management. - * - * @param location the location to check - */ - void checkAndUpdateClockState(Location location); - - /** - * Add a new redstone clock test at the specified location. - * - * @param location the location to test - */ - void addRedstoneClockTest(Location location); - - /** - * Reload the service configuration. - */ - void reload(); - - /** - * Remove a clock by its location. - * - * @param location the location of the clock to remove - */ - void removeClockByLocation(Location location); - - /** - * Remove a clock by the clock object itself. - * - * @param redstoneClock the clock to remove - */ - void removeClockByClock(RedstoneClock redstoneClock); - - /** - * Check if the service contains a clock at the specified location. - * - * @param location the location to check - * @return true if a clock exists at the location, false otherwise - */ - boolean containsLocation(Location location); - - /** - * Get the clock at the specified location. - * - * @param location the location to check - * @return the clock at the location, or null if none exists - */ - @Nullable - RedstoneClock getClockByLocation(Location location); - - /** - * Get all active redstone clocks. - * - * @return an unmodifiable collection of all redstone clocks - */ - Collection getRedstoneClocks(); - - /** - * Get all locations with active redstone clocks. - * - * @return an unmodifiable collection of all clock locations - */ - Collection getRedstoneClockLocations(); - - /** - * Get all active clock testers as a map. - * - * @return a copy of the active testers map - */ - Map getActiveTester(); -} \ No newline at end of file diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/RedstoneTrackingService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/RedstoneTrackingService.java new file mode 100644 index 00000000..acc851e1 --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/api/RedstoneTrackingService.java @@ -0,0 +1,24 @@ +package net.onelitefeather.antiredstoneclockremastered.service.api; + +import net.onelitefeather.antiredstoneclockremastered.model.RedstoneClock; +import net.onelitefeather.antiredstoneclockremastered.model.StaticRedstoneClock; +import org.bukkit.Location; + +import java.util.Collection; + +/** + * Service for tracking redstone signals. + * + * @author TheMeinerLP + * @version 1.0.0 + * @since 2.4.0 + */ +public interface RedstoneTrackingService { + + boolean isRedstoneClock(RedstoneClockMiddleware.CheckContext context); + + Collection getRedstoneClocks(); + + void removeClockByLocation(Location location); + +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/PlotSquaredRedstoneClockMiddleware.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/PlotSquaredRedstoneClockMiddleware.java new file mode 100644 index 00000000..09c5859f --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/PlotSquaredRedstoneClockMiddleware.java @@ -0,0 +1,22 @@ +package net.onelitefeather.antiredstoneclockremastered.service.chain; + +import jakarta.inject.Inject; +import net.onelitefeather.antiredstoneclockremastered.api.PlotsquaredSupport; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import org.jetbrains.annotations.NotNull; + +public final class PlotSquaredRedstoneClockMiddleware extends RedstoneClockMiddleware { + + private final PlotsquaredSupport plotsquaredSupport; + + @Inject + public PlotSquaredRedstoneClockMiddleware(PlotsquaredSupport plotsquaredSupport) { + this.plotsquaredSupport = plotsquaredSupport; + } + + @Override + public @NotNull ResultState check(@NotNull CheckContext context) { + if (this.plotsquaredSupport.isAllowedPlot(context.location())) return ResultState.SKIP; + return checkNext(context); + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/SkipEventTypeRedstoneClockMiddleware.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/SkipEventTypeRedstoneClockMiddleware.java new file mode 100644 index 00000000..733598de --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/SkipEventTypeRedstoneClockMiddleware.java @@ -0,0 +1,36 @@ +package net.onelitefeather.antiredstoneclockremastered.service.chain; + +import jakarta.inject.Inject; +import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import org.jetbrains.annotations.NotNull; + +public final class SkipEventTypeRedstoneClockMiddleware extends RedstoneClockMiddleware { + + private final AntiRedstoneClockRemastered antiRedstoneClockRemastered; + + @Inject + public SkipEventTypeRedstoneClockMiddleware(AntiRedstoneClockRemastered antiRedstoneClockRemastered) { + this.antiRedstoneClockRemastered = antiRedstoneClockRemastered; + } + + @Override + public @NotNull ResultState check(@NotNull CheckContext context) { + if (context.eventType() == EventType.SCULK_SENSOR && + this.antiRedstoneClockRemastered.getConfig().getBoolean("check.sculkSensor")) + return checkNext(context); + if (context.eventType() == EventType.REDSTONE_AND_REPEATER && + this.antiRedstoneClockRemastered.getConfig().getBoolean("check.redstoneAndRepeater")) + return checkNext(context); + if (context.eventType() == EventType.PISTON && + this.antiRedstoneClockRemastered.getConfig().getBoolean("check.piston")) + return checkNext(context); + if (context.eventType() == EventType.OBSERVER && + this.antiRedstoneClockRemastered.getConfig().getBoolean("check.observer")) + return checkNext(context); + if (context.eventType() == EventType.COMPARATOR && + this.antiRedstoneClockRemastered.getConfig().getBoolean("check.comparator")) + return checkNext(context); + return ResultState.SKIP; + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/TPSRedstoneClockMiddleware.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/TPSRedstoneClockMiddleware.java new file mode 100644 index 00000000..1f098d81 --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/TPSRedstoneClockMiddleware.java @@ -0,0 +1,22 @@ +package net.onelitefeather.antiredstoneclockremastered.service.chain; + +import jakarta.inject.Inject; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import net.onelitefeather.antiredstoneclockremastered.utils.CheckTPS; +import org.jetbrains.annotations.NotNull; + +public final class TPSRedstoneClockMiddleware extends RedstoneClockMiddleware { + + private final CheckTPS checkTPS; + + @Inject + public TPSRedstoneClockMiddleware(CheckTPS checkTPS) { + this.checkTPS = checkTPS; + } + + @Override + public @NotNull ResultState check(@NotNull CheckContext context) { + if (!this.checkTPS.isTpsOk()) return ResultState.SKIP; + return checkNext(context); + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/TrackingRedstoneClockMiddleware.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/TrackingRedstoneClockMiddleware.java new file mode 100644 index 00000000..30d4e8cc --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/TrackingRedstoneClockMiddleware.java @@ -0,0 +1,32 @@ +package net.onelitefeather.antiredstoneclockremastered.service.chain; + +import jakarta.inject.Inject; +import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneTrackingService; +import org.jetbrains.annotations.NotNull; + +public final class TrackingRedstoneClockMiddleware extends RedstoneClockMiddleware { + + private final RedstoneTrackingService trackingService; + private final AntiRedstoneClockRemastered antiRedstoneClockRemastered; + + @Inject + public TrackingRedstoneClockMiddleware(RedstoneTrackingService trackingService, + AntiRedstoneClockRemastered antiRedstoneClockRemastered) { + this.trackingService = trackingService; + this.antiRedstoneClockRemastered = antiRedstoneClockRemastered; + } + + @Override + public @NotNull ResultState check(@NotNull CheckContext context) { + if (this.trackingService.isRedstoneClock(context)) { + var autoBreak = this.antiRedstoneClockRemastered.getConfig().getBoolean("clock.autoBreak", true); + if (!autoBreak) return ResultState.ONLY_NOTIFY; + var autoDrop = this.antiRedstoneClockRemastered.getConfig().getBoolean("clock.drop", false); + if (autoDrop) return ResultState.REMOVE_AND_DROP; + return ResultState.REMOVE_AND_WITHOUT_DROP; + } + return ResultState.SKIP; + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/WorldGuardRedstoneClockMiddleware.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/WorldGuardRedstoneClockMiddleware.java new file mode 100644 index 00000000..d76e5858 --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/WorldGuardRedstoneClockMiddleware.java @@ -0,0 +1,22 @@ +package net.onelitefeather.antiredstoneclockremastered.service.chain; + +import jakarta.inject.Inject; +import net.onelitefeather.antiredstoneclockremastered.api.WorldGuardSupport; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import org.jetbrains.annotations.NotNull; + +public final class WorldGuardRedstoneClockMiddleware extends RedstoneClockMiddleware { + + private final WorldGuardSupport worldGuardSupport; + + @Inject + public WorldGuardRedstoneClockMiddleware(WorldGuardSupport worldGuardSupport) { + this.worldGuardSupport = worldGuardSupport; + } + + @Override + public @NotNull ResultState check(@NotNull CheckContext context) { + if (this.worldGuardSupport.isRegionAllowed(context.location())) return ResultState.SKIP; + return checkNext(context); + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/WorldRedstoneClockMiddleware.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/WorldRedstoneClockMiddleware.java new file mode 100644 index 00000000..47b08fba --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/chain/WorldRedstoneClockMiddleware.java @@ -0,0 +1,23 @@ +package net.onelitefeather.antiredstoneclockremastered.service.chain; + +import jakarta.inject.Inject; +import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import org.jetbrains.annotations.NotNull; + +public final class WorldRedstoneClockMiddleware extends RedstoneClockMiddleware { + + private final AntiRedstoneClockRemastered antiRedstoneClockRemastered; + + @Inject + public WorldRedstoneClockMiddleware(AntiRedstoneClockRemastered antiRedstoneClockRemastered) { + this.antiRedstoneClockRemastered = antiRedstoneClockRemastered; + } + + @Override + public @NotNull ResultState check(@NotNull CheckContext context) { + var ignoredWorlds = this.antiRedstoneClockRemastered.getConfig().getStringList("check.ignoredWorlds"); + if (ignoredWorlds.contains(context.location().getWorld().getName())) return ResultState.SKIP; + return checkNext(context); + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/decision/BukkitDecisionService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/decision/BukkitDecisionService.java new file mode 100644 index 00000000..051b22d9 --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/decision/BukkitDecisionService.java @@ -0,0 +1,79 @@ +package net.onelitefeather.antiredstoneclockremastered.service.decision; + +import jakarta.inject.Inject; +import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; +import net.onelitefeather.antiredstoneclockremastered.service.api.DecisionService; +import net.onelitefeather.antiredstoneclockremastered.service.api.NotificationService; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import net.onelitefeather.antiredstoneclockremastered.service.api.RegionService; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * Bukkit/Paper implementation of the RedstoneClockService. + * This implementation uses the standard Bukkit scheduler and APIs. + * + * @author TheMeinerLP + * @version 2.2.0 + * @since 1.0.0 + */ +public final class BukkitDecisionService implements DecisionService { + + private final @NotNull AntiRedstoneClockRemastered antiRedstoneClockRemastered; + private final RegionService regionService; + private final NotificationService notificationService; + private final RedstoneClockMiddleware redstoneClockMiddleware; + + private final ItemStack SILK_TOUCH_PICKAXE = new ItemStack(Material.DIAMOND_PICKAXE); + + @Inject + public BukkitDecisionService(@NotNull AntiRedstoneClockRemastered antiRedstoneClockRemastered, + RedstoneClockMiddleware redstoneClockMiddleware, + RegionService regionService, NotificationService notificationService) { + this.antiRedstoneClockRemastered = antiRedstoneClockRemastered; + this.redstoneClockMiddleware = redstoneClockMiddleware; + this.regionService = regionService; + this.notificationService = notificationService; + SILK_TOUCH_PICKAXE.addEnchantment(Enchantment.SILK_TOUCH, 1); + } + + @Override + public void makeDecisionWithContext(RedstoneClockMiddleware.@NotNull CheckContext context) { + var resultState = this.redstoneClockMiddleware.check(context); + if (resultState == RedstoneClockMiddleware.ResultState.SKIP) { + return; + } + this.notificationService.sendNotificationMessage(context.location()); + if (resultState == RedstoneClockMiddleware.ResultState.ONLY_NOTIFY) { + return; + } + + var location = context.location(); + + if (resultState == RedstoneClockMiddleware.ResultState.REMOVE_AND_DROP) { + Block block = location.getBlock(); + var drops = block.getDrops(SILK_TOUCH_PICKAXE); + drops.forEach(itemStack -> block.getWorld().dropItem(location, itemStack)); + Runnable removeTask = () -> block.setType(Material.AIR, true); + if (this.regionService.isRegionOwner(location)) { + this.regionService.executeInRegion(location, removeTask); + } + return; + } + if (resultState == RedstoneClockMiddleware.ResultState.REMOVE_AND_WITHOUT_DROP) { + Block block = location.getBlock(); + Runnable removeTask = () -> block.setType(Material.AIR, true); + if (this.regionService.isRegionOwner(location)) { + this.regionService.executeInRegion(location, removeTask); + } + } + } + + @Override + public void reload() { + this.antiRedstoneClockRemastered.reloadConfig(); + } +} \ No newline at end of file diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/DecisionServiceFactory.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/DecisionServiceFactory.java new file mode 100644 index 00000000..c5f78625 --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/DecisionServiceFactory.java @@ -0,0 +1,42 @@ +package net.onelitefeather.antiredstoneclockremastered.service.factory; + +import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; +import net.onelitefeather.antiredstoneclockremastered.service.api.NotificationService; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import net.onelitefeather.antiredstoneclockremastered.service.api.DecisionService; +import net.onelitefeather.antiredstoneclockremastered.service.api.RegionService; +import net.onelitefeather.antiredstoneclockremastered.service.decision.BukkitDecisionService; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Factory for creating RedstoneClockService implementations. + * This factory determines the appropriate implementation based on the server platform. + * + * @author TheMeinerLP + * @version 2.2.0 + * @since 1.0.0 + */ +public final class DecisionServiceFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(DecisionServiceFactory.class); + + private DecisionServiceFactory() { + // Utility class + } + + /** + * Creates the appropriate RedstoneClockService implementation for the current platform. + * + * @param plugin the main plugin instance + * @return the appropriate RedstoneClockService implementation + */ + @NotNull + public static DecisionService createService(@NotNull AntiRedstoneClockRemastered plugin, + RegionService regionService, RedstoneClockMiddleware middleware, + NotificationService notificationService) { + LOGGER.info("Using BukkitDecisionService as DecisionService implementation."); + return new BukkitDecisionService(plugin, middleware, regionService, notificationService); + } +} \ No newline at end of file diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/RedstoneClockServiceFactory.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/RedstoneClockServiceFactory.java deleted file mode 100644 index 48ab5548..00000000 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/RedstoneClockServiceFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.onelitefeather.antiredstoneclockremastered.service.factory; - -import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; -import net.onelitefeather.antiredstoneclockremastered.api.PlotsquaredSupport; -import net.onelitefeather.antiredstoneclockremastered.api.WorldGuardSupport; -import net.onelitefeather.antiredstoneclockremastered.service.api.NotificationService; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; -import net.onelitefeather.antiredstoneclockremastered.service.api.RegionService; -import net.onelitefeather.antiredstoneclockremastered.service.impl.BukkitRedstoneClockService; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static net.onelitefeather.antiredstoneclockremastered.service.factory.FoliaHelper.isFolia; - -/** - * Factory for creating RedstoneClockService implementations. - * This factory determines the appropriate implementation based on the server platform. - * - * @author TheMeinerLP - * @version 2.2.0 - * @since 1.0.0 - */ -public final class RedstoneClockServiceFactory { - - private static final Logger LOGGER = LoggerFactory.getLogger(RedstoneClockServiceFactory.class); - - private RedstoneClockServiceFactory() { - // Utility class - } - - /** - * Creates the appropriate RedstoneClockService implementation for the current platform. - * - * @param plugin the main plugin instance - * @return the appropriate RedstoneClockService implementation - */ - @NotNull - public static RedstoneClockService createService(@NotNull AntiRedstoneClockRemastered plugin, - RegionService regionService, PlotsquaredSupport plotsquaredSupport, - WorldGuardSupport worldGuardSupport, - NotificationService notificationService) { - if (FoliaHelper.isFolia()) { - LOGGER.info("Folia detected - using FoliaRedstoneClockService"); - // Uncomment when ready to enable Folia support: - // return new FoliaRedstoneClockService(plugin); - LOGGER.warn("Folia implementation not yet ready, falling back to Bukkit implementation"); - } - - LOGGER.info("Using BukkitRedstoneClockService"); - return new BukkitRedstoneClockService(plugin, regionService, worldGuardSupport, plotsquaredSupport, notificationService); - } -} \ No newline at end of file diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/RegionServiceFactory.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/RegionServiceFactory.java index ab4b270e..0e8ef897 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/RegionServiceFactory.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/RegionServiceFactory.java @@ -2,8 +2,8 @@ import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; import net.onelitefeather.antiredstoneclockremastered.service.api.RegionService; -import net.onelitefeather.antiredstoneclockremastered.service.impl.BukkitRegionService; -import net.onelitefeather.antiredstoneclockremastered.service.impl.FoliaRegionService; +import net.onelitefeather.antiredstoneclockremastered.service.region.BukkitRegionService; +import net.onelitefeather.antiredstoneclockremastered.service.region.FoliaRegionService; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/SchedulerServiceFactory.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/SchedulerServiceFactory.java index e838d161..9b65b753 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/SchedulerServiceFactory.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/factory/SchedulerServiceFactory.java @@ -2,8 +2,8 @@ import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; import net.onelitefeather.antiredstoneclockremastered.service.api.SchedulerService; -import net.onelitefeather.antiredstoneclockremastered.service.impl.BukkitSchedulerService; -import net.onelitefeather.antiredstoneclockremastered.service.impl.FoliaSchedulerService; +import net.onelitefeather.antiredstoneclockremastered.service.scheduler.BukkitSchedulerService; +import net.onelitefeather.antiredstoneclockremastered.service.scheduler.FoliaSchedulerService; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/BukkitRedstoneClockService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/BukkitRedstoneClockService.java deleted file mode 100644 index 608e35d5..00000000 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/BukkitRedstoneClockService.java +++ /dev/null @@ -1,241 +0,0 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; - -import jakarta.inject.Inject; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; -import net.onelitefeather.antiredstoneclockremastered.api.PlotsquaredSupport; -import net.onelitefeather.antiredstoneclockremastered.api.WorldGuardSupport; -import net.onelitefeather.antiredstoneclockremastered.model.RedstoneClock; -import net.onelitefeather.antiredstoneclockremastered.service.api.NotificationService; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; -import net.onelitefeather.antiredstoneclockremastered.service.api.RegionService; -import net.onelitefeather.antiredstoneclockremastered.utils.Constants; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Level; - -/** - * Bukkit/Paper implementation of the RedstoneClockService. - * This implementation uses the standard Bukkit scheduler and APIs. - * - * @author TheMeinerLP - * @version 2.2.0 - * @since 1.0.0 - */ -public final class BukkitRedstoneClockService implements RedstoneClockService { - - private final @NotNull AntiRedstoneClockRemastered antiRedstoneClockRemastered; - private final RegionService regionService; - private final WorldGuardSupport worldGuardSupport; - private final PlotsquaredSupport plotsquaredSupport; - private final NotificationService notificationService; - private int endTimeDelay; - private int maxClockCount; - private boolean autoBreakBlock; - private boolean dropItems; - private List ignoredWorlds; - - private final ConcurrentHashMap activeClockTesters = new ConcurrentHashMap<>(); - private final ItemStack SILK_TOUCH_PICKAXE = new ItemStack(Material.DIAMOND_PICKAXE); - - @Inject - public BukkitRedstoneClockService(@NotNull AntiRedstoneClockRemastered antiRedstoneClockRemastered, - RegionService regionService, WorldGuardSupport worldGuardSupport, - PlotsquaredSupport plotsquaredSupport, NotificationService notificationService) { - this.antiRedstoneClockRemastered = antiRedstoneClockRemastered; - this.endTimeDelay = antiRedstoneClockRemastered.getConfig().getInt("clock.endDelay", 300); - this.maxClockCount = antiRedstoneClockRemastered.getConfig().getInt("clock.maxCount", 150); - this.autoBreakBlock = antiRedstoneClockRemastered.getConfig().getBoolean("clock.autoBreak", true); - this.dropItems = antiRedstoneClockRemastered.getConfig().getBoolean("clock.drop", false); - this.ignoredWorlds = antiRedstoneClockRemastered.getConfig().getStringList("check.ignoredWorlds"); - this.regionService = regionService; - this.worldGuardSupport = worldGuardSupport; - this.plotsquaredSupport = plotsquaredSupport; - this.notificationService = notificationService; - SILK_TOUCH_PICKAXE.addEnchantment(Enchantment.SILK_TOUCH, 1); - } - - @Override - public void checkAndUpdateClockStateWithActiveManual(@NotNull Location location, boolean state) { - if (this.ignoredWorlds.contains(location.getWorld().getName())) return; - if (this.worldGuardSupport.isRegionAllowed(location)) - return; - if (this.plotsquaredSupport.isAllowedPlot(location)) - return; - var clock = getClockByLocation(location); - if (clock != null) { - if (clock.isActive()) { - if (clock.isTimeOut()) { - removeClockByClock(clock); - return; - } - if (clock.getTriggerCount() >= this.maxClockCount) { - destroyRedstoneClock(location, clock); - return; - } - clock.incrementTriggerCount(); - clock.setActive(false); - return; - } else { - clock.setActive(state); - } - } - addRedstoneClockTest(location); - } - - @Override - public void checkAndUpdateClockStateWithActiveManual(@NotNull Block block, boolean state) { - checkAndUpdateClockStateWithActiveManual(block.getLocation(), state); - } - - @Override - public void checkAndUpdateClockStateWithActive(@NotNull Block block) { - checkAndUpdateClockStateWithActive(block.getLocation()); - } - - @Override - public void checkAndUpdateClockStateWithActive(@NotNull Location location) { - if (this.ignoredWorlds.contains(location.getWorld().getName())) return; - if (this.worldGuardSupport.isRegionAllowed(location)) - return; - if (this.plotsquaredSupport.isAllowedPlot(location)) - return; - var clock = getClockByLocation(location); - if (clock != null) { - if (clock.isActive()) { - if (clock.isTimeOut()) { - removeClockByClock(clock); - return; - } - if (clock.getTriggerCount() >= this.maxClockCount) { - destroyRedstoneClock(location, clock); - return; - } - clock.incrementTriggerCount(); - clock.setActive(false); - return; - } else { - clock.setActive(true); - } - } - addRedstoneClockTest(location); - } - - @Override - public void checkAndUpdateClockState(@NotNull Block block) { - checkAndUpdateClockState(block.getLocation()); - } - - @Override - public void checkAndUpdateClockState(@NotNull Location location) { - if (this.ignoredWorlds.contains(location.getWorld().getName())) return; - if (this.worldGuardSupport.isRegionAllowed(location)) - return; - if (this.plotsquaredSupport.isAllowedPlot(location)) - return; - var clock = getClockByLocation(location); - if (clock != null) { - if (clock.isTimeOut()) { - removeClockByClock(clock); - return; - } - if (clock.getTriggerCount() >= this.maxClockCount) { - destroyRedstoneClock(location, clock); - return; - } - clock.incrementTriggerCount(); - return; - } - addRedstoneClockTest(location); - } - - private void destroyRedstoneClock(@NotNull Location location, @NotNull RedstoneClock clock) { - if (this.autoBreakBlock) breakBlock(location); - if (!clock.isDetected()) { - clock.setDetected(true); - this.notificationService.sendNotificationMessage(location); - } - removeClockByClock(clock); - } - - private void breakBlock(@NotNull Location location) { - Block block = location.getBlock(); - if (this.dropItems) { - var drops = block.getDrops(SILK_TOUCH_PICKAXE); - drops.forEach(itemStack -> block.getWorld().dropItem(location, itemStack)); - } - Runnable removeTask = () -> block.setType(Material.AIR, true); - if (this.regionService.isRegionOwner(location)) { - this.regionService.executeInRegion(location, removeTask); - } - - } - - @Override - public void addRedstoneClockTest(@NotNull Location location) { - this.activeClockTesters.putIfAbsent(location, new RedstoneClock(location, (System.currentTimeMillis() / 1000) + endTimeDelay)); - } - - @Override - public void reload() { - this.antiRedstoneClockRemastered.reloadConfig(); - this.endTimeDelay = antiRedstoneClockRemastered.getConfig().getInt("clock.endDelay", 300); - this.maxClockCount = antiRedstoneClockRemastered.getConfig().getInt("clock.maxCount", 150); - this.autoBreakBlock = antiRedstoneClockRemastered.getConfig().getBoolean("clock.autoBreak", true); - this.dropItems = antiRedstoneClockRemastered.getConfig().getBoolean("clock.drop", false); - this.ignoredWorlds = antiRedstoneClockRemastered.getConfig().getStringList("check.ignoredWorlds"); - } - - @Override - public void removeClockByLocation(@NotNull Location location) { - this.activeClockTesters.remove(location); - } - - @Override - public void removeClockByClock(@NotNull RedstoneClock redstoneClock) { - removeClockByLocation(redstoneClock.getLocation()); - } - - @Override - public boolean containsLocation(@NotNull Location location) { - return this.activeClockTesters.containsKey(location); - } - - @Override - @Nullable - public RedstoneClock getClockByLocation(@NotNull Location location) { - return this.activeClockTesters.get(location); - } - - @Override - @NotNull - public Collection getRedstoneClocks() { - return Collections.unmodifiableCollection(this.activeClockTesters.values()); - } - - @Override - @NotNull - public Collection getRedstoneClockLocations() { - return Collections.unmodifiableCollection(this.activeClockTesters.keySet()); - } - - @Override - @NotNull - public Map getActiveTester() { - return Map.copyOf(this.activeClockTesters); - } -} \ No newline at end of file diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/FoliaRedstoneClockService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/FoliaRedstoneClockService.java deleted file mode 100644 index caa03cae..00000000 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/FoliaRedstoneClockService.java +++ /dev/null @@ -1,126 +0,0 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; - -import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; -import net.onelitefeather.antiredstoneclockremastered.model.RedstoneClock; -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.Map; - -/** - * Placeholder implementation for Folia platform support. - * This demonstrates how a future Folia implementation would be structured - * using the Service Layer Architecture. - * - * When implementing for Folia, this class would handle: - * - Region-based scheduling - * - Thread-safe operations across regions - * - Folia-specific async execution patterns - */ -public final class FoliaRedstoneClockService implements RedstoneClockService { - - private final AntiRedstoneClockRemastered plugin; - - public FoliaRedstoneClockService(@NotNull AntiRedstoneClockRemastered plugin) { - this.plugin = plugin; - // TODO: Initialize Folia-specific components - // - RegionizedTaskManager for region-aware scheduling - // - Thread-safe collections for multi-region access - // - Region-based notification systems - } - - @Override - public void checkAndUpdateClockStateWithActiveManual(@NotNull Location location, boolean state) { - // TODO: Implement Folia-specific region-aware clock state checking - // Use RegionizedTaskManager.execute() for region-based operations - throw new UnsupportedOperationException("Folia implementation not yet available"); - } - - @Override - public void checkAndUpdateClockStateWithActiveManual(@NotNull Block block, boolean state) { - checkAndUpdateClockStateWithActiveManual(block.getLocation(), state); - } - - @Override - public void checkAndUpdateClockStateWithActive(@NotNull Block block) { - checkAndUpdateClockStateWithActive(block.getLocation()); - } - - @Override - public void checkAndUpdateClockStateWithActive(@NotNull Location location) { - // TODO: Implement Folia-specific region-aware clock state checking - throw new UnsupportedOperationException("Folia implementation not yet available"); - } - - @Override - public void checkAndUpdateClockState(@NotNull Block block) { - checkAndUpdateClockState(block.getLocation()); - } - - @Override - public void checkAndUpdateClockState(@NotNull Location location) { - // TODO: Implement Folia-specific region-aware clock state checking - throw new UnsupportedOperationException("Folia implementation not yet available"); - } - - @Override - public void addRedstoneClockTest(@NotNull Location location) { - // TODO: Implement Folia-specific region-aware clock test addition - throw new UnsupportedOperationException("Folia implementation not yet available"); - } - - @Override - public void reload() { - // TODO: Implement Folia-specific configuration reloading - throw new UnsupportedOperationException("Folia implementation not yet available"); - } - - @Override - public void removeClockByLocation(@NotNull Location location) { - // TODO: Implement Folia-specific region-aware clock removal - throw new UnsupportedOperationException("Folia implementation not yet available"); - } - - @Override - public void removeClockByClock(@NotNull RedstoneClock redstoneClock) { - removeClockByLocation(redstoneClock.getLocation()); - } - - @Override - public boolean containsLocation(@NotNull Location location) { - // TODO: Implement Folia-specific region-aware location checking - throw new UnsupportedOperationException("Folia implementation not yet available"); - } - - @Override - @Nullable - public RedstoneClock getClockByLocation(@NotNull Location location) { - // TODO: Implement Folia-specific region-aware clock retrieval - throw new UnsupportedOperationException("Folia implementation not yet available"); - } - - @Override - @NotNull - public Collection getRedstoneClocks() { - // TODO: Implement Folia-specific cross-region clock collection - throw new UnsupportedOperationException("Folia implementation not yet available"); - } - - @Override - @NotNull - public Collection getRedstoneClockLocations() { - // TODO: Implement Folia-specific cross-region location collection - throw new UnsupportedOperationException("Folia implementation not yet available"); - } - - @Override - @NotNull - public Map getActiveTester() { - // TODO: Implement Folia-specific cross-region active tester map - throw new UnsupportedOperationException("Folia implementation not yet available"); - } -} \ No newline at end of file diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/AdminNotificationService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/AdminNotificationService.java similarity index 96% rename from src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/AdminNotificationService.java rename to src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/AdminNotificationService.java index 0224f822..e19d5b98 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/AdminNotificationService.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/AdminNotificationService.java @@ -1,4 +1,4 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; +package net.onelitefeather.antiredstoneclockremastered.service.notification; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/ConsoleNotificationService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/ConsoleNotificationService.java similarity index 96% rename from src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/ConsoleNotificationService.java rename to src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/ConsoleNotificationService.java index 210e7c43..3e01c3d4 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/ConsoleNotificationService.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/ConsoleNotificationService.java @@ -1,4 +1,4 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; +package net.onelitefeather.antiredstoneclockremastered.service.notification; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/DiscordNotificationService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/DiscordNotificationService.java similarity index 95% rename from src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/DiscordNotificationService.java rename to src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/DiscordNotificationService.java index 53d408ac..a34839e6 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/DiscordNotificationService.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/DiscordNotificationService.java @@ -1,9 +1,8 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; +package net.onelitefeather.antiredstoneclockremastered.service.notification; import club.minnced.discord.webhook.WebhookClient; import club.minnced.discord.webhook.send.WebhookEmbed; import club.minnced.discord.webhook.send.WebhookEmbedBuilder; -import com.google.common.collect.Maps; import dev.vankka.mcdiscordreserializer.discord.DiscordSerializer; import dev.vankka.mcdiscordreserializer.discord.DiscordSerializerOptions; import net.kyori.adventure.text.Component; @@ -14,16 +13,11 @@ import net.onelitefeather.antiredstoneclockremastered.service.api.NotificationService; import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.configuration.Configuration; -import org.bukkit.configuration.MemoryConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/SignNotificationService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/SignNotificationService.java similarity index 98% rename from src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/SignNotificationService.java rename to src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/SignNotificationService.java index 3eed02ea..da1e2469 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/SignNotificationService.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/notification/SignNotificationService.java @@ -1,4 +1,4 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; +package net.onelitefeather.antiredstoneclockremastered.service.notification; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.logger.slf4j.ComponentLogger; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/BukkitRegionService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/region/BukkitRegionService.java similarity index 92% rename from src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/BukkitRegionService.java rename to src/main/java/net/onelitefeather/antiredstoneclockremastered/service/region/BukkitRegionService.java index 91f61c27..e7af1813 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/BukkitRegionService.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/region/BukkitRegionService.java @@ -1,4 +1,4 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; +package net.onelitefeather.antiredstoneclockremastered.service.region; import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; import net.onelitefeather.antiredstoneclockremastered.service.api.RegionService; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/FoliaRegionService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/region/FoliaRegionService.java similarity index 93% rename from src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/FoliaRegionService.java rename to src/main/java/net/onelitefeather/antiredstoneclockremastered/service/region/FoliaRegionService.java index aea8f9a8..3418c59b 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/FoliaRegionService.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/region/FoliaRegionService.java @@ -1,4 +1,4 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; +package net.onelitefeather.antiredstoneclockremastered.service.region; import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; import net.onelitefeather.antiredstoneclockremastered.service.api.RegionService; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/BukkitSchedulerService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/scheduler/BukkitSchedulerService.java similarity index 94% rename from src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/BukkitSchedulerService.java rename to src/main/java/net/onelitefeather/antiredstoneclockremastered/service/scheduler/BukkitSchedulerService.java index aaa9a091..5d58c7fd 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/BukkitSchedulerService.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/scheduler/BukkitSchedulerService.java @@ -1,4 +1,4 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; +package net.onelitefeather.antiredstoneclockremastered.service.scheduler; import io.papermc.paper.threadedregions.scheduler.ScheduledTask; import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/FoliaSchedulerService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/scheduler/FoliaSchedulerService.java similarity index 94% rename from src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/FoliaSchedulerService.java rename to src/main/java/net/onelitefeather/antiredstoneclockremastered/service/scheduler/FoliaSchedulerService.java index 2e9706ef..c4bc5887 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/FoliaSchedulerService.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/scheduler/FoliaSchedulerService.java @@ -1,4 +1,4 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; +package net.onelitefeather.antiredstoneclockremastered.service.scheduler; import io.papermc.paper.threadedregions.scheduler.ScheduledTask; import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/ConfigMode.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/ConfigMode.java new file mode 100644 index 00000000..8ca71e97 --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/ConfigMode.java @@ -0,0 +1,44 @@ +package net.onelitefeather.antiredstoneclockremastered.service.tracking; + +import net.kyori.adventure.text.Component; +import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; +import org.bukkit.configuration.Configuration; +import org.bukkit.configuration.file.FileConfiguration; + +/** + * Enumeration for configuration modes. + * + * @author TheMeinerLP + * @since 2.5.0 + * @version 1.0.0 + */ +public enum ConfigMode { + DYNAMIC(Component.translatable("antiredstoneclockremastered.notify.checkmode.dynamic").arguments(AntiRedstoneClockRemastered.PREFIX)), + STATIC(Component.translatable("antiredstoneclockremastered.notify.checkmode.static").arguments(AntiRedstoneClockRemastered.PREFIX)); + + private static final ConfigMode[] VALUES = values(); + + private final Component enableMessage; + + ConfigMode(Component enableMessage) { + this.enableMessage = enableMessage; + } + + public Component getEnableMessage() { + return enableMessage; + } + + public static ConfigMode getByName(String name) { + for (ConfigMode mode : VALUES) { + if (mode.name().equalsIgnoreCase(name)) { + return mode; + } + } + return STATIC; + } + + public static ConfigMode getEnum(Configuration configuration, String path, ConfigMode defaultMode) { + String modeName = configuration.getString(path, defaultMode.name()); + return getByName(modeName); + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/DelegatedTrackingService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/DelegatedTrackingService.java new file mode 100644 index 00000000..603af3c3 --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/DelegatedTrackingService.java @@ -0,0 +1,54 @@ +package net.onelitefeather.antiredstoneclockremastered.service.tracking; + +import jakarta.inject.Inject; +import jakarta.inject.Named; +import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; +import net.onelitefeather.antiredstoneclockremastered.model.RedstoneClock; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneTrackingService; +import org.bukkit.Location; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public final class DelegatedTrackingService implements RedstoneTrackingService { + + private static final Logger LOGGER = LoggerFactory.getLogger(DelegatedTrackingService.class); + private final RedstoneTrackingService staticTrackingService; + private final RedstoneTrackingService dynamicTrackingService; + private final AntiRedstoneClockRemastered plugin; + + @Inject + public DelegatedTrackingService(@Named("staticTrackingService") RedstoneTrackingService staticTrackingService, + @Named("dynamicTrackingService") RedstoneTrackingService dynamicTrackingService, + AntiRedstoneClockRemastered plugin) { + this.staticTrackingService = staticTrackingService; + this.dynamicTrackingService = dynamicTrackingService; + this.plugin = plugin; + } + + @Override + public boolean isRedstoneClock(RedstoneClockMiddleware.CheckContext context) { + var mode = ConfigMode.getEnum(this.plugin.getConfig(), "check.mode", ConfigMode.STATIC); + return switch (mode) { + case STATIC -> this.staticTrackingService.isRedstoneClock(context); + case DYNAMIC -> this.dynamicTrackingService.isRedstoneClock(context); + }; + } + + @Override + public Collection getRedstoneClocks() { + List redstoneClocks = new ArrayList<>(this.dynamicTrackingService.getRedstoneClocks()); + redstoneClocks.addAll(this.staticTrackingService.getRedstoneClocks()); + return redstoneClocks; + } + + @Override + public void removeClockByLocation(Location location) { + this.staticTrackingService.removeClockByLocation(location); + this.dynamicTrackingService.removeClockByLocation(location); + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/DynamicTrackingService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/DynamicTrackingService.java new file mode 100644 index 00000000..1948b1bf --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/DynamicTrackingService.java @@ -0,0 +1,109 @@ +package net.onelitefeather.antiredstoneclockremastered.service.tracking; + +import com.jeff_media.customblockdata.CustomBlockData; +import jakarta.inject.Inject; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; +import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; +import net.onelitefeather.antiredstoneclockremastered.model.DynamicRedstoneClock; +import net.onelitefeather.antiredstoneclockremastered.model.RedstoneClock; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneTrackingService; +import net.onelitefeather.antiredstoneclockremastered.utils.UUIDTagType; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.metadata.FixedMetadataValue; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public final class DynamicTrackingService implements RedstoneTrackingService { + + private static final ComponentLogger LOGGER = ComponentLogger.logger(DynamicTrackingService.class); + private static final NamespacedKey REDSTONE_CLOCK_METADATA_KEY = NamespacedKey.fromString("antiredstoneclock:redstone_clock"); + private final ConcurrentHashMap activeClockTesters = new ConcurrentHashMap<>(); + private final AntiRedstoneClockRemastered plugin; + + @Inject + public DynamicTrackingService(AntiRedstoneClockRemastered plugin) { + this.plugin = plugin; + } + + @Override + public boolean isRedstoneClock(RedstoneClockMiddleware.@NotNull CheckContext context) { + var eventType = context.eventType(); + var location = context.location(); + final boolean desiredState = Optional.ofNullable(context.state()).orElse(false); + var clock = getClockByLocation(location); + if (clock != null) { + if (expireOrDestroyIfNeeded(clock)) return true; + + if (eventType == RedstoneClockMiddleware.EventType.REDSTONE_AND_REPEATER) { + clock.incrementTriggerCount(); + clock.setCurrentLocation(location); + } else { + if (clock.isActive()) { + clock.incrementTriggerCount(); + clock.setCurrentLocation(location); + clock.setActive(false); + return false; + } else { + clock.setActive(desiredState); + } + } + } + addRedstoneClockTest(location); + return false; + } + + private boolean expireOrDestroyIfNeeded(@NotNull DynamicRedstoneClock clock) { + if (clock.isTimeOut()) { + removeClockByClock(clock); + return false; + } + if (clock.getTriggerCount() >= plugin.getConfig().getInt("clock.maxCount", 150)) { + removeClockByClock(clock); + return true; + } + return false; + } + + public void removeClockByClock(@NotNull DynamicRedstoneClock staticRedstoneClock) { + removeClockByLocation(staticRedstoneClock.getCurrentLocation()); + } + + private DynamicRedstoneClock getClockByLocation(Location location) { + var block = location.getBlock(); + var customBlockData = new CustomBlockData(block, this.plugin); + if (customBlockData.has(REDSTONE_CLOCK_METADATA_KEY)) { + var uuid = customBlockData.get(REDSTONE_CLOCK_METADATA_KEY, UUIDTagType.UUID); + return this.activeClockTesters.get(uuid); + } + return null; + } + + public void addRedstoneClockTest(@NotNull Location location) { + var block = location.getBlock(); + var customBlockData = new CustomBlockData(block, this.plugin); + if (customBlockData.has(REDSTONE_CLOCK_METADATA_KEY)) { + return; + } + var dynamicRedstoneClock = new DynamicRedstoneClock(location, (System.currentTimeMillis() / 1000) + plugin.getConfig().getInt("clock.endDelay", 300)); + customBlockData.set(REDSTONE_CLOCK_METADATA_KEY, UUIDTagType.UUID, dynamicRedstoneClock.getUuid()); + this.activeClockTesters.put(dynamicRedstoneClock.getUuid(), dynamicRedstoneClock); + } + + + @Override + public Collection getRedstoneClocks() { + return Collections.unmodifiableCollection(this.activeClockTesters.values()); + } + + @Override + public void removeClockByLocation(Location location) { + this.activeClockTesters.values().removeIf(dynamicRedstoneClock -> dynamicRedstoneClock.getCurrentLocation().equals(location)); + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/StaticTrackingService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/StaticTrackingService.java new file mode 100644 index 00000000..85d8f545 --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/tracking/StaticTrackingService.java @@ -0,0 +1,111 @@ +package net.onelitefeather.antiredstoneclockremastered.service.tracking; + +import jakarta.inject.Inject; +import jakarta.inject.Named; +import net.onelitefeather.antiredstoneclockremastered.AntiRedstoneClockRemastered; +import net.onelitefeather.antiredstoneclockremastered.model.RedstoneClock; +import net.onelitefeather.antiredstoneclockremastered.model.StaticRedstoneClock; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockMiddleware; +import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneTrackingService; +import org.bukkit.Location; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +@Named("staticTrackingService") +public final class StaticTrackingService implements RedstoneTrackingService { + + private final ConcurrentHashMap activeClockTesters = new ConcurrentHashMap<>(); + + private final AntiRedstoneClockRemastered antiRedstoneClockRemastered; + + @Inject + public StaticTrackingService(AntiRedstoneClockRemastered antiRedstoneClockRemastered) { + this.antiRedstoneClockRemastered = antiRedstoneClockRemastered; + } + + @Override + public boolean isRedstoneClock(RedstoneClockMiddleware.@NotNull CheckContext context) { + var eventType = context.eventType(); + var location = context.location(); + final boolean desiredState = Optional.ofNullable(context.state()).orElse(false); + var clock = getClockByLocation(location); + if (clock != null) { + if (expireOrDestroyIfNeeded(clock)) return true; + + if (eventType == RedstoneClockMiddleware.EventType.REDSTONE_AND_REPEATER) { + clock.incrementTriggerCount(); + } else { + if (clock.isActive()) { + clock.incrementTriggerCount(); + clock.setActive(false); + return false; + } else { + clock.setActive(desiredState); + } + } + } + addRedstoneClockTest(location); + return false; + } + + private boolean expireOrDestroyIfNeeded(@NotNull StaticRedstoneClock clock) { + if (clock.isTimeOut()) { + removeClockByClock(clock); + return false; + } + if (clock.getTriggerCount() >= antiRedstoneClockRemastered.getConfig().getInt("clock.maxCount", 150)) { + removeClockByClock(clock); + return true; + } + return false; + } + + public void addRedstoneClockTest(@NotNull Location location) { + this.activeClockTesters.putIfAbsent(location, new StaticRedstoneClock(location, (System.currentTimeMillis() / 1000) + antiRedstoneClockRemastered.getConfig().getInt("clock.endDelay", 300))); + } + + + public void removeClockByLocation(@NotNull Location location) { + this.activeClockTesters.remove(location); + } + + + public void removeClockByClock(@NotNull StaticRedstoneClock staticRedstoneClock) { + removeClockByLocation(staticRedstoneClock.getLocation()); + } + + + public boolean containsLocation(@NotNull Location location) { + return this.activeClockTesters.containsKey(location); + } + + + @Nullable + public StaticRedstoneClock getClockByLocation(@NotNull Location location) { + return this.activeClockTesters.get(location); + } + + + @Override + @NotNull + public Collection getRedstoneClocks() { + return Collections.unmodifiableCollection(this.activeClockTesters.values()); + } + + + @NotNull + public Collection getRedstoneClockLocations() { + return Collections.unmodifiableCollection(this.activeClockTesters.keySet()); + } + + @NotNull + public Map getActiveTester() { + return Map.copyOf(this.activeClockTesters); + } +} diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/LegacyTranslationService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/translation/LegacyTranslationService.java similarity index 94% rename from src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/LegacyTranslationService.java rename to src/main/java/net/onelitefeather/antiredstoneclockremastered/service/translation/LegacyTranslationService.java index 988863d9..62a887e0 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/LegacyTranslationService.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/translation/LegacyTranslationService.java @@ -1,4 +1,4 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; +package net.onelitefeather.antiredstoneclockremastered.service.translation; import net.kyori.adventure.key.Key; import net.kyori.adventure.translation.GlobalTranslator; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/ModernTranslationService.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/translation/ModernTranslationService.java similarity index 93% rename from src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/ModernTranslationService.java rename to src/main/java/net/onelitefeather/antiredstoneclockremastered/service/translation/ModernTranslationService.java index a013a533..4093171c 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/impl/ModernTranslationService.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/service/translation/ModernTranslationService.java @@ -1,4 +1,4 @@ -package net.onelitefeather.antiredstoneclockremastered.service.impl; +package net.onelitefeather.antiredstoneclockremastered.service.translation; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.minimessage.translation.MiniMessageTranslationStore; diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/utils/CheckTPS.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/utils/CheckTPS.java index d03db2d1..3410f17d 100644 --- a/src/main/java/net/onelitefeather/antiredstoneclockremastered/utils/CheckTPS.java +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/utils/CheckTPS.java @@ -11,7 +11,6 @@ public final class CheckTPS { private long lastPoll = System.currentTimeMillis(); private boolean tpsOk = true; private long tps = 20; - private final AntiRedstoneClockRemastered plugin; private final SchedulerService scheduler; private final int interval; private final int maximimumTPS; @@ -19,7 +18,6 @@ public final class CheckTPS { @Inject public CheckTPS(AntiRedstoneClockRemastered plugin, SchedulerService scheduler) { - this.plugin = plugin; this.scheduler = scheduler; this.interval = plugin.getConfig().getInt("tps.interval", 2); this.maximimumTPS = plugin.getConfig().getInt("tps.max", 20); diff --git a/src/main/java/net/onelitefeather/antiredstoneclockremastered/utils/UUIDTagType.java b/src/main/java/net/onelitefeather/antiredstoneclockremastered/utils/UUIDTagType.java new file mode 100644 index 00000000..388044ae --- /dev/null +++ b/src/main/java/net/onelitefeather/antiredstoneclockremastered/utils/UUIDTagType.java @@ -0,0 +1,39 @@ +package net.onelitefeather.antiredstoneclockremastered.utils; + +import org.bukkit.persistence.PersistentDataAdapterContext; +import org.bukkit.persistence.PersistentDataType; + +import java.nio.ByteBuffer; +import java.util.UUID; + +public final class UUIDTagType implements PersistentDataType { + + public static final UUIDTagType UUID = new UUIDTagType(); + + @Override + public Class getPrimitiveType() { + return byte[].class; + } + + @Override + public Class getComplexType() { + return UUID.class; + } + + @Override + public byte[] toPrimitive(UUID complex, PersistentDataAdapterContext context) { + ByteBuffer bb = ByteBuffer.wrap(new byte[16]); + bb.putLong(complex.getMostSignificantBits()); + bb.putLong(complex.getLeastSignificantBits()); + return bb.array(); + } + + @Override + public UUID fromPrimitive(byte[] primitive, PersistentDataAdapterContext context) { + ByteBuffer bb = ByteBuffer.wrap(primitive); + long firstLong = bb.getLong(); + long secondLong = bb.getLong(); + return new UUID(firstLong, secondLong); + } + +} diff --git a/src/main/resources/antiredstoneclockremasterd.properties b/src/main/resources/antiredstoneclockremasterd.properties index f64c7627..bf2fe2b6 100644 --- a/src/main/resources/antiredstoneclockremasterd.properties +++ b/src/main/resources/antiredstoneclockremasterd.properties @@ -29,4 +29,6 @@ antiredstoneclockremastered.command.feature.clock.set.maxCount.description=To keep the project alive, we ask for donations to our https://opencollective.com/onelitefeather/projects/antiredstoneclock-remastered antiredstoneclockremastered.notify.donation.player= To keep the project alive, we ask for donations to our OpenCollective antiredstoneclockremastered.notify.update.player= Your version() is older than our latest published version (). Please update as soon as possible to get continued support. Or click me to get on the download page! -antiredstoneclockremastered.notify.update.console=Your version() is older than our latest published version (). Please update as soon as possible to get continued support. Or click use this link \ No newline at end of file +antiredstoneclockremastered.notify.update.console=Your version() is older than our latest published version (). Please update as soon as possible to get continued support. Or click use this link +antiredstoneclockremastered.notify.checkmode.dynamic= Dynamic Check Mode is enabled. This may lead to higher CPU usage but better detection rates. +antiredstoneclockremastered.notify.checkmode.static= Static Check Mode is enabled. This may lead to lower CPU usage but okaish detection rates. \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 8ebe2ff2..cf3bfa2c 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,6 +1,8 @@ translations: - 'en-US' + check: + mode: 'dynamic' # 'dynamic' or 'static' redstoneAndRepeater: true observer: true piston: true diff --git a/src/test/java/net/onelitefeather/antiredstoneclockremastered/commands/DisplayActiveClocksCommandTest.java b/src/test/java/net/onelitefeather/antiredstoneclockremastered/commands/DisplayActiveClocksCommandTest.java deleted file mode 100644 index 97b7207e..00000000 --- a/src/test/java/net/onelitefeather/antiredstoneclockremastered/commands/DisplayActiveClocksCommandTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package net.onelitefeather.antiredstoneclockremastered.commands; - -import net.onelitefeather.antiredstoneclockremastered.service.api.RedstoneClockService; -import org.junit.jupiter.api.*; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.Collections; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -/** - * Unit tests for DisplayActiveClocksCommand verifying dependency injection functionality. - * These tests focus on testing the command behavior in isolation using mocked dependencies. - * - * @author OneLiteFeather - * @since 2.2.0 - * @version 1.0.0 - */ -@ExtendWith(MockitoExtension.class) -@DisplayName("DisplayActiveClocksCommand Unit Tests") -class DisplayActiveClocksCommandTest { - - @Mock - private RedstoneClockService mockRedstoneClockService; - - private DisplayActiveClocksCommand command; - - @BeforeEach - void setUp() { - // Create command with mocked dependencies (no MockBukkit needed for unit tests) - command = new DisplayActiveClocksCommand(mockRedstoneClockService); - } - - @Test - @DisplayName("Should initialize command with injected dependencies") - void shouldInitializeWithInjectedDependencies() { - // Then - assertThat(command).isNotNull(); - // Verify that the command uses dependency injection pattern - assertThat(command).hasFieldOrProperty("redstoneClockService"); - } - - @Test - @DisplayName("Should not accept null dependencies") - void shouldNotAcceptNullDependencies() { - // The constructor doesn't throw NPE, so let's test a different aspect - // We can test that the command gracefully handles null service scenario - - // When - DisplayActiveClocksCommand commandWithNull = new DisplayActiveClocksCommand(null); - - // Then - assertThat(commandWithNull).isNotNull(); - // The command should be created but the service field should be null - } - - @Test - @DisplayName("Should use dependency injection pattern") - void shouldUseDependencyInjectionPattern() { - // When - command = new DisplayActiveClocksCommand(mockRedstoneClockService); - - // Then - assertThat(command).isNotNull(); - // Don't stub methods we don't use to avoid unnecessary stubbing warnings - } - - @Test - @DisplayName("Should handle service calls during execution simulation") - void shouldHandleServiceCallsDuringExecutionSimulation() { - // Given - when(mockRedstoneClockService.getRedstoneClocks()).thenReturn(Collections.emptyList()); - - // When - // Simulate what happens during command execution - var clocks = mockRedstoneClockService.getRedstoneClocks(); - - // Then - assertThat(clocks).isEmpty(); - verify(mockRedstoneClockService, times(1)).getRedstoneClocks(); - } -} \ No newline at end of file diff --git a/src/test/resources/config.yml b/src/test/resources/config.yml index 98ef9899..3b4765b3 100644 --- a/src/test/resources/config.yml +++ b/src/test/resources/config.yml @@ -18,4 +18,4 @@ check: comparator: true # Test settings -testMode: true \ No newline at end of file +testMode: true