Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee1bf8216e | ||
|
|
362d871ab8 | ||
|
|
738101d5d4 | ||
|
|
782d58fcac | ||
|
|
94b1e77a98 |
No files matched your search
@@ -1 +0,0 @@
|
||||
.gitea/CODEOWNERS linguist-detectable=false
|
||||
@@ -1,3 +0,0 @@
|
||||
# Pull requests request review from the eligible staff team(s).
|
||||
# One approval from either an Admin or Developer satisfies branch protection.
|
||||
* @trueog/Admins @trueog/Developers
|
||||
@@ -1,2 +0,0 @@
|
||||
github: Multiverse
|
||||
open_collective: multiverse-plugins
|
||||
@@ -18,10 +18,10 @@ body:
|
||||
|
||||
When completing the report, please ensure all fields are filled with the correct details requested. Failure to do so will result in your issue being closed.
|
||||
- type: input
|
||||
id: multiverse-version-info
|
||||
id: mutliverse-version-info
|
||||
attributes:
|
||||
label: '`/mv dumps` output'
|
||||
description: Run `/mv dumps` in the console, then copy and paste the link from the output of the command into this box. If `/mv dumps` command is not available, update multiverse to v5.
|
||||
label: '`/mv version -p` output'
|
||||
description: Run `/mv version -p` in the console, then copy and paste the link from the output of the command into this box.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
@@ -29,7 +29,7 @@ body:
|
||||
attributes:
|
||||
label: Server logs
|
||||
description: >
|
||||
Include full startup log and console error (if any). upload all relevant logs to either https://pastes.dev
|
||||
Include full startup log and console error (if any). upload all relevant logs to either https://paste.gg
|
||||
or https://gist.github.com, save and the paste the link in this box.
|
||||
validations:
|
||||
required: true
|
||||
@@ -54,7 +54,7 @@ body:
|
||||
id: reproduce-steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Provide detailed instructions to trigger the bug.
|
||||
description: Provide detailed intructions to trigger the bug.
|
||||
placeholder: |
|
||||
Example:
|
||||
1. Start a server with only multiverse installed.
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
name: 'Dispatch: Create Release'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_type:
|
||||
description: 'Stable or pre-release'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- prerelease
|
||||
- release
|
||||
version_bump:
|
||||
description: 'Version bump type'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- major
|
||||
- minor
|
||||
- patch
|
||||
|
||||
jobs:
|
||||
github_release:
|
||||
uses: ./.github/workflows/call.github_release.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
release_mode: ${{ inputs.release_type }}
|
||||
version_bump: ${{ inputs.version_bump }}
|
||||
|
||||
platform_uploads:
|
||||
needs: github_release
|
||||
if: needs.github_release.outputs.release_created == 'true'
|
||||
uses: ./.github/workflows/call.platform_uploads.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
target_tag: ${{ needs.github_release.outputs.tag_name }}
|
||||
upload_modrinth: 'true'
|
||||
upload_dbo: 'false'
|
||||
upload_hangar: 'false'
|
||||
@@ -1,55 +0,0 @@
|
||||
name: 'Dispatch: Deploy Javadoc'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
target_tag:
|
||||
description: 'Version to generate javadoc'
|
||||
required: true
|
||||
replace_latest:
|
||||
description: 'Replace the latest folder'
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
javadocs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.target_tag }}
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'adopt'
|
||||
cache: gradle
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
|
||||
- name: build javadoc
|
||||
run: ./gradlew javadoc
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_VERSION: ${{ inputs.target_tag }}
|
||||
|
||||
- name: Copy javadoc to deploy folder
|
||||
run: |
|
||||
mkdir -p build/docs/javadoc-deploy/${{ inputs.target_tag }}
|
||||
cp -r build/docs/javadoc/* build/docs/javadoc-deploy/${{ inputs.target_tag }}
|
||||
|
||||
- name: Copy javadoc to latest folder
|
||||
if: inputs.replace_latest
|
||||
run: |
|
||||
mkdir -p build/docs/javadoc-deploy/latest
|
||||
cp -r build/docs/javadoc/* build/docs/javadoc-deploy/latest
|
||||
|
||||
- name: Deploy javadoc to gh pages
|
||||
uses: JamesIves/github-pages-deploy-action@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
folder: build/docs/javadoc-deploy
|
||||
branch: javadoc
|
||||
target-folder: javadoc
|
||||
clean: false
|
||||
commit-message: Deploy javadoc for ${{ inputs.target_tag }}
|
||||
@@ -11,9 +11,9 @@ jobs:
|
||||
pull-requests: write
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: dbelyaev/action-checkstyle@v3
|
||||
- uses: dbelyaev/action-checkstyle@v0.8.4
|
||||
continue-on-error: true
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -43,28 +43,28 @@ jobs:
|
||||
echo "version_bump: ${{ inputs.version_bump }}"
|
||||
echo "promote_from: ${{ inputs.promote_from }}"
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ inputs.promote_from }}
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '21'
|
||||
java-version: '11'
|
||||
distribution: 'adopt'
|
||||
cache: gradle
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
- name: Validate Gradle wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
- name: Build to test
|
||||
id: test
|
||||
run: ./gradlew clean build -x assemble -x shadowJar
|
||||
- name: Build and test
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: clean build -x assemble -x shadowJar
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create release
|
||||
id: release
|
||||
if: steps.test.outcome == 'success'
|
||||
uses: benwoo1110/semantic-release-action@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -74,58 +74,18 @@ jobs:
|
||||
|
||||
- name: Publish package
|
||||
if: steps.release.outputs.release_created == 'true'
|
||||
run: >
|
||||
./gradlew publish -x test
|
||||
-PmultiverseUsername=${{ secrets.REPOSILITE_REPO_USERNAME }}
|
||||
-PmultiversePassword=${{ secrets.REPOSILITE_REPO_PASSWORD }}
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: publish -x test
|
||||
env:
|
||||
GITHUB_VERSION: ${{ steps.release.outputs.publish_version }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build for upload
|
||||
id: build
|
||||
if: steps.release.outputs.release_created == 'true'
|
||||
run: ./gradlew build -x test
|
||||
env:
|
||||
GITHUB_VERSION: ${{ steps.release.outputs.tag_name }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload release artifact
|
||||
if: steps.build.outcome == 'success'
|
||||
if: steps.release.outputs.release_created == 'true'
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: build/libs/${{ inputs.plugin_name }}-${{ steps.release.outputs.tag_name }}.jar
|
||||
file: build/libs/${{ inputs.plugin_name }}-${{ steps.release.outputs.publish_version }}.jar
|
||||
asset_name: ${{ inputs.plugin_name }}-${{ steps.release.outputs.tag_name }}.jar
|
||||
tag: ${{ steps.release.outputs.tag_name }}
|
||||
|
||||
- name: Generate javadoc
|
||||
id: javadoc
|
||||
if: steps.build.outcome == 'success'
|
||||
run: ./gradlew javadoc -x test
|
||||
env:
|
||||
GITHUB_VERSION: ${{ steps.release.outputs.publish_version }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload javadoc
|
||||
if: steps.javadoc.outcome == 'success'
|
||||
run: |
|
||||
mkdir -p build/docs/javadoc-deploy/${{ steps.release.outputs.publish_version }}
|
||||
cp -r build/docs/javadoc/* build/docs/javadoc-deploy/${{ steps.release.outputs.publish_version }}
|
||||
|
||||
- name: Override latest javadoc for stable release
|
||||
if: steps.javadoc.outcome == 'success' && steps.release.outputs.release_type == 'release'
|
||||
run: |
|
||||
mkdir -p build/docs/javadoc-deploy/latest
|
||||
cp -r build/docs/javadoc/* build/docs/javadoc-deploy/latest
|
||||
|
||||
- name: Deploy javadoc to gh pages
|
||||
if: steps.javadoc.outcome == 'success'
|
||||
uses: JamesIves/github-pages-deploy-action@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
folder: build/docs/javadoc-deploy
|
||||
branch: javadoc
|
||||
target-folder: javadoc
|
||||
clean: false
|
||||
commit-message: Deploy javadoc for ${{ steps.release.outputs.tag_name }}
|
||||
@@ -107,9 +107,9 @@ jobs:
|
||||
files: '["${{ github.workspace }}/${{ inputs.plugin_name }}-${{ steps.release-info.outputs.tag_name }}.jar"]'
|
||||
name: ${{ steps.release-info.outputs.tag_name }}
|
||||
changelog: ${{ steps.release-artifact.outputs.body }}
|
||||
game_versions: 1.21.11, 1.21.10, 1.21.9, 1.21.8, 1.21.7, 1.21.6, 1.21.5, 1.21.4, 1.21.3, 1.21.2, 1.21.1, 1.21, 1.20.6, 1.20.5, 1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2
|
||||
game_versions: 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13
|
||||
version_type: ${{ steps.parse-release-type.outputs.release_type }}
|
||||
loaders: bukkit, spigot, paper, purpur
|
||||
loaders: bukkit, spigot, paper
|
||||
dependencies: ${{ inputs.modrinth_dependencies }}
|
||||
|
||||
- name: Upload to DBO
|
||||
@@ -121,7 +121,7 @@ jobs:
|
||||
changelog: ${{ steps.release-artifact.outputs.body }}
|
||||
changelog_type: markdown
|
||||
display_name: ${{ steps.release-info.outputs.tag_name }}
|
||||
game_versions: 1.21.11, 1.21.10, 1.21.9, 1.21.8, 1.21.7, 1.21.6, 1.21.5, 1.21.4, 1.21.3, 1.21.2, 1.21.1, 1.21, 1.20.6, 1.20.5, 1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2
|
||||
game_versions: 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17, 1.16, 1.15, 1.14, 1.13
|
||||
release_type: ${{ steps.parse-release-type.outputs.release_type }}
|
||||
project_relations: ${{ inputs.dbo_project_relations }}
|
||||
file_path: ${{ github.workspace }}/${{ inputs.plugin_name }}-${{ steps.release-info.outputs.tag_name }}.jar
|
||||
@@ -136,5 +136,5 @@ jobs:
|
||||
channel: ${{ steps.parse-release-type.outputs.release_type }}
|
||||
files: '[{"path": "${{ github.workspace }}/${{ inputs.plugin_name }}-${{ steps.release-info.outputs.tag_name }}.jar", "platforms": ["PAPER"]}]'
|
||||
description: ${{ steps.release-artifact.outputs.body }}
|
||||
platform_dependencies: '{"PAPER": ["1.18.2-1.21.11"]}'
|
||||
platform_dependencies: '{"PAPER": ["1.13-1.20.1"]}'
|
||||
plugin_dependencies: ${{ inputs.hangar_plugin_dependencies }}
|
||||
@@ -9,40 +9,32 @@ on:
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
test-and-artifact:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '21'
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
cache: gradle
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
- name: Validate Gradle wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
- name: Run unit tests
|
||||
run: ./gradlew build
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: build
|
||||
env:
|
||||
GITHUB_VERSION: pr${{ github.event.pull_request.number }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Artifact output
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.plugin_name }}-pr${{ github.event.pull_request.number }}
|
||||
path: build/libs/${{ inputs.plugin_name }}-pr${{ github.event.pull_request.number }}.jar
|
||||
|
||||
comment-artifact:
|
||||
needs: test-and-artifact
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: benwoo1110/artifact-comment-action@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,4 +0,0 @@
|
||||
kotlin version: 2.0.21
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
|
||||
1. Kotlin compile daemon is ready
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
<p align="center">
|
||||
<img src="config/multiverse-banner.png" alt="Multiverse Logo">
|
||||
<img src="config/multiverse2-long.png" alt="Multiverse Logo">
|
||||
</p>
|
||||
|
||||
[](https://modrinth.com/plugin/multiverse-core)
|
||||
[](https://hangar.papermc.io/Multiverse/Multiverse-Core)
|
||||
[](https://dev.bukkit.org/projects/multiverse-core)
|
||||
[](https://www.spigotmc.org/resources/multiverse-core.390/)
|
||||
[](https://hangar.papermc.io/Multiverse/Multiverse-Core)
|
||||
[](https://dev.bukkit.org/projects/multiverse-core)
|
||||
[](https://www.spigotmc.org/resources/multiverse-core.390/)
|
||||
|
||||
[](https://dev.bukkit.org/projects/multiverse-core)
|
||||
[](https://ci.onarandombox.com/job/Multiverse-Core/)
|
||||
[](https://discord.gg/NZtfKky)
|
||||
[](https://patreon.com/dumptruckman)
|
||||
[](LICENSE.md)
|
||||
|
||||
[](https://github.com/Multiverse/Multiverse-Core/releases/latest)
|
||||
[](https://github.com/Multiverse/Multiverse-Core/releases)
|
||||
[](https://discord.gg/NZtfKky)
|
||||
[](https://github.com/sponsors/Multiverse)
|
||||
[](https://opencollective.com/multiverse-plugins)
|
||||
|
||||
# About
|
||||
|
||||
[Multiverse](https://modrinth.com/plugin/multiverse-core) was created at the dawn of Bukkit multiworld support. It has since then grown into a **complete world management solution!** Multiverse provides the easiest to use world management solution for your Minecraft server, big or small, and with great addons like [Portals](https://dev.bukkit.org/projects/multiverse-portals) and [NetherPortals](https://dev.bukkit.org/projects/multiverse-netherportals/), what's not to love!
|
||||
[Multiverse](https://dev.bukkit.org/projects/multiverse-core) was created at the dawn of Bukkit multiworld support. It has since then grown into a **complete world management solution!** Multiverse provides the easiest to use world management solution for your Minecraft server, big or small, and with great addons like [Portals](https://dev.bukkit.org/projects/multiverse-portals) and [NetherPortals](https://dev.bukkit.org/projects/multiverse-netherportals/), what's not to love!
|
||||
|
||||
Now it's time to create your very own Multiverse server, do check out our [Wiki](https://github.com/Multiverse/Multiverse-Core/wiki) and [Usage Guide](https://github.com/Multiverse/Multiverse-Core/wiki/Basics) to get started. Feel free to hop onto our [Discord](https://discord.gg/NZtfKky) if you have any question or just want to have a chat with us!
|
||||
|
||||
@@ -26,24 +27,22 @@ Now it's time to create your very own Multiverse server, do check out our [Wiki]
|
||||
* [Multiverse-Inventories](https://github.com/Multiverse/Multiverse-Inventories) -> Have separated players stats and inventories per world or per group of worlds.
|
||||
* [Multiverse-SignPortals](https://github.com/Multiverse/Multiverse-SignPortals) -> Signs as teleporters!
|
||||
|
||||
## Usage Guide
|
||||
|
||||
We have a cool new website hosting our Wiki: https://mvplugins.org
|
||||
|
||||
## Building
|
||||
Simply build the source with Gradle:
|
||||
```
|
||||
./gradlew build
|
||||
```
|
||||
More details are available on the [build instructions wiki page](https://github.com/Multiverse/Multiverse-Core/wiki/Building).
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
**Want to help improve Multiverse?** There are several ways you can support and contribute to the project.
|
||||
* Take a look at our "Bug: Unconfirmed" issues, where you can find issues that need extra testing and investigation.
|
||||
* Want others to love Multiverse too? You can join the [Multiverse Discord community](https://discord.gg/NZtfKky) and help others with issues and setup!
|
||||
* A Multiverse guru? You can update our [Wiki](https://github.com/Multiverse/multiverse-web) with your latest tip, tricks and guides! The wiki open for all to edit and improve.
|
||||
* A Multiverse guru? You can update our [Wiki](https://github.com/Multiverse/Multiverse-Core/wiki) with your latest tip, tricks and guides! The wiki open for all to edit and improve.
|
||||
* Love coding? You could look at ["State: Open to PR"](https://github.com/Multiverse/Multiverse-Core/labels/State%3A%20Open%20to%20PR) and ["Resolution: Accepted"](https://github.com/Multiverse/Multiverse-Core/labels/Resolution%3A%20Accepted) issues. We're always happy to receive bug fixes and feature additions as [pull requests](https://www.freecodecamp.org/news/how-to-make-your-first-pull-request-on-github-3/).
|
||||
* If you'd like to make a financial contribution to the project, do consider donating to our [Github Sponsors](https://github.com/sponsors/Multiverse) or [Open Collective](https://opencollective.com/multiverse-plugins)!
|
||||
* If you'd like to make a financial contribution to the project, do consider joining our [Patreon](https://www.patreon.com/dumptruckman) or make a one-time donation [here](https://paypal.me/dumptruckman)!
|
||||
|
||||
Additionally, we would like to give a big thanks to everyone that has supported Multiverse over the years, as well as those in the years to come. Thank you!
|
||||
|
||||
|
||||
+321
@@ -0,0 +1,321 @@
|
||||
import org.apache.tools.ant.filters.ReplaceTokens
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'com.github.johnrengelman.shadow' version '7.1.2'
|
||||
id "org.jetbrains.kotlin.jvm" version "1.8.10"
|
||||
}
|
||||
|
||||
version = System.getenv('GITHUB_VERSION') ?: 'local'
|
||||
group = 'com.onarandombox.multiversecore'
|
||||
description = 'Multiverse-Core'
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(17))
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
|
||||
maven {
|
||||
url = uri('https://hub.spigotmc.org/nexus/content/repositories/snapshots/')
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri('https://repo.onarandombox.com/content/groups/public')
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri('https://hub.spigotmc.org/nexus/content/groups/public/')
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri('https://jitpack.io')
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri('https://repo.minebench.de/')
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri('https://repo.maven.apache.org/maven2/')
|
||||
}
|
||||
|
||||
maven {
|
||||
name = 'aikar repo'
|
||||
url = uri('https://repo.aikar.co/content/groups/aikar/')
|
||||
}
|
||||
|
||||
maven {
|
||||
name = 'glaremasters repo'
|
||||
url = 'https://repo.glaremasters.me/repository/towny/'
|
||||
}
|
||||
|
||||
maven {
|
||||
name = 'PlaceholderAPI'
|
||||
url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/'
|
||||
}
|
||||
|
||||
maven {
|
||||
name = 'papermc repo'
|
||||
url = 'https://repo.papermc.io/repository/maven-public/'
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
// Add configuration for server API
|
||||
compileOnly.extendsFrom serverApi
|
||||
runtimeClasspath.extendsFrom serverApi
|
||||
|
||||
// Add configuration for external plugins
|
||||
implementation.extendsFrom externalPlugin
|
||||
|
||||
// Add configuration for dependencies that will be included in fat jar
|
||||
compileClasspath.extendsFrom shadowed
|
||||
testCompileClasspath.extendsFrom shadowed
|
||||
testRuntimeClasspath.extendsFrom shadowed
|
||||
oldTestCompileClasspath.extendsFrom shadowed
|
||||
oldTestRuntimeClasspath.extendsFrom shadowed
|
||||
|
||||
// Add configuration for old tests
|
||||
oldTestImplementation.extendsFrom implementation
|
||||
oldTestRuntime.extendsFrom runtime
|
||||
}
|
||||
|
||||
dependencies {
|
||||
serverApi 'org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT'
|
||||
|
||||
// Economy
|
||||
externalPlugin('com.github.MilkBowl:VaultAPI:1.7.1') {
|
||||
exclude group: 'org.bukkit', module: 'bukkit'
|
||||
}
|
||||
|
||||
// PlaceholderAPI
|
||||
externalPlugin 'me.clip:placeholderapi:2.11.3'
|
||||
|
||||
// Command Framework
|
||||
shadowed 'co.aikar:acf-paper:0.5.1-SNAPSHOT'
|
||||
|
||||
// Config
|
||||
shadowed('me.main__.util:SerializationConfig:1.7') {
|
||||
exclude group: 'org.bukkit', module: 'bukkit'
|
||||
}
|
||||
shadowed('io.github.townyadvanced.commentedconfiguration:CommentedConfiguration:1.0.1') {
|
||||
exclude group: 'org.spigotmc', module: 'spigot-api'
|
||||
}
|
||||
|
||||
// Utils
|
||||
shadowed 'io.vavr:vavr:0.10.4'
|
||||
shadowed 'org.glassfish.hk2:hk2-locator:3.0.3'
|
||||
shadowed('com.dumptruckman.minecraft:Logging:1.1.1') {
|
||||
exclude group: 'junit', module: 'junit'
|
||||
}
|
||||
shadowed 'de.themoep.idconverter:mappings:1.2-SNAPSHOT'
|
||||
shadowed 'org.bstats:bstats-bukkit:2.2.1'
|
||||
shadowed 'net.minidev:json-smart:2.4.9'
|
||||
shadowed 'org.jetbrains:annotations:22.0.0'
|
||||
shadowed 'io.papermc:paperlib:1.0.8'
|
||||
|
||||
// Tests
|
||||
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10'
|
||||
testImplementation 'com.github.seeseemelk:MockBukkit-v1.20:3.20.2'
|
||||
testImplementation('com.googlecode.json-simple:json-simple:1.1.1') {
|
||||
exclude group: 'junit', module: 'junit'
|
||||
}
|
||||
testImplementation 'org.jetbrains.kotlin:kotlin-test'
|
||||
testImplementation 'com.natpryce:hamkrest:1.8.0.1'
|
||||
testImplementation 'org.mockito.kotlin:mockito-kotlin:4.1.0'
|
||||
|
||||
// Old Tests
|
||||
oldTestImplementation 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
|
||||
oldTestImplementation('com.googlecode.json-simple:json-simple:1.1.1') {
|
||||
exclude group: 'junit', module: 'junit'
|
||||
}
|
||||
oldTestImplementation 'junit:junit:4.13.1'
|
||||
oldTestImplementation 'org.mockito:mockito-core:3.11.2'
|
||||
oldTestImplementation 'commons-io:commons-io:2.7'
|
||||
|
||||
// Annotation Processors
|
||||
annotationProcessor 'org.glassfish.hk2:hk2-metadata-generator:3.0.3'
|
||||
testAnnotationProcessor 'org.glassfish.hk2:hk2-metadata-generator:3.0.3'
|
||||
}
|
||||
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
tasks.withType(Javadoc) {
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
|
||||
configurations {
|
||||
[apiElements, runtimeElements].each {
|
||||
it.outgoing.artifacts.removeIf { it.buildDependencies.getDependencies(null).contains(jar) }
|
||||
it.outgoing.artifact(shadowJar)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sourceSets {
|
||||
oldTest {
|
||||
java {
|
||||
compileClasspath += main.output
|
||||
runtimeClasspath += main.output
|
||||
srcDir file('src/old-test/java')
|
||||
}
|
||||
resources.srcDir file('src/old-test/resources')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
from components.java
|
||||
|
||||
pom.withXml {
|
||||
Node pomNode = asNode()
|
||||
|
||||
// Remove Kotlin dependency
|
||||
pomNode.dependencies.'*'.findAll() {
|
||||
it.groupId.text() == 'org.jetbrains.kotlin'
|
||||
}.each() {
|
||||
it.parent().remove(it)
|
||||
}
|
||||
|
||||
// Switch runtime deps to provided
|
||||
pomNode.dependencies.'*'.findAll() {
|
||||
it.scope.text() == 'runtime'
|
||||
}.each() {
|
||||
it.scope*.value = 'provided'
|
||||
}
|
||||
|
||||
// Add spigot api to pom
|
||||
project.configurations.serverApi.allDependencies.each { dependency ->
|
||||
pomNode.dependencies[0].appendNode("dependency").with {
|
||||
it.appendNode("groupId", dependency.group)
|
||||
it.appendNode("artifactId", dependency.name)
|
||||
it.appendNode("version", dependency.version)
|
||||
it.appendNode("scope", "provided")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
name = "GitHubPackages"
|
||||
url = "https://maven.pkg.github.com/Multiverse/Multiverse-Core"
|
||||
credentials {
|
||||
username = System.getenv("GITHUB_ACTOR")
|
||||
password = System.getenv("GITHUB_TOKEN")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ext.bitlyAccessToken = System.getenv('BITLY_ACCESS_TOKEN') ?: 'bitly-access-token'
|
||||
|
||||
task prepareSource(type: Sync) {
|
||||
inputs.property 'bitlyAccessToken', bitlyAccessToken
|
||||
from sourceSets.main.java
|
||||
into "$buildDir/src"
|
||||
filter(ReplaceTokens, tokens: [
|
||||
'bitly-access-token': bitlyAccessToken,
|
||||
])
|
||||
}
|
||||
|
||||
compileJava {
|
||||
source = prepareSource.outputs
|
||||
}
|
||||
tasks.withType(JavaCompile) {
|
||||
configure(options) {
|
||||
options.compilerArgs << '-Aorg.glassfish.hk2.metadata.location=META-INF/hk2-locator/Multiverse-Core'
|
||||
}
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
// We're not using Kotlin in the plugin itself, just tests!
|
||||
enabled = false
|
||||
}
|
||||
configurations.findAll { !it.name.startsWith('test') }.each {
|
||||
it.exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
|
||||
}
|
||||
|
||||
processResources {
|
||||
def props = [version: "${project.version}"]
|
||||
inputs.properties props
|
||||
filteringCharset 'UTF-8'
|
||||
filesMatching('plugin.yml') {
|
||||
expand props
|
||||
}
|
||||
|
||||
// This task should never be skipped. The tests depend on this having been run but we want the new version number
|
||||
// that is created after tests are run and before we run again to publish.
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
|
||||
javadoc {
|
||||
source = sourceSets.main.allJava
|
||||
classpath = configurations.compileClasspath
|
||||
}
|
||||
|
||||
|
||||
project.configurations.api.canBeResolved = true
|
||||
|
||||
shadowJar {
|
||||
relocate 'co.aikar', 'org.mvplugins.multiverse.external.acf'
|
||||
relocate 'com.dumptruckman.minecraft.util.Logging', 'org.mvplugins.multiverse.core.utils.CoreLogging'
|
||||
relocate 'com.dumptruckman.minecraft.util.DebugLog', 'org.mvplugins.multiverse.core.utils.DebugFileLogger'
|
||||
relocate 'de.themoep.idconverter', 'org.mvplugins.multiverse.external.idconverter'
|
||||
relocate 'io.github.townyadvanced.commentedconfiguration', 'org.mvplugins.multiverse.external.commentedconfiguration'
|
||||
relocate 'me.main__.util', 'org.mvplugins.multiverse.external.serializationconfig'
|
||||
relocate 'org.bstats', 'org.mvplugins.multiverse.external.bstats'
|
||||
relocate 'com.sun', 'org.mvplugins.multiverse.external.sun'
|
||||
relocate 'net.minidev', 'org.mvplugins.multiverse.external.minidev'
|
||||
relocate 'org.objectweb', 'org.mvplugins.multiverse.external.objectweb'
|
||||
relocate 'io.vavr', 'org.mvplugins.multiverse.external.vavr'
|
||||
relocate 'jakarta', 'org.mvplugins.multiverse.external.jakarta'
|
||||
relocate 'javassist', 'org.mvplugins.multiverse.external.javassist'
|
||||
relocate 'org.aopalliance', 'org.mvplugins.multiverse.external.aopalliance'
|
||||
relocate 'org.glassfish', 'org.mvplugins.multiverse.external.glassfish'
|
||||
relocate 'org.jvnet', 'org.mvplugins.multiverse.external.jvnet'
|
||||
relocate 'org.intellij', 'org.mvplugins.multiverse.external.intellij'
|
||||
relocate 'org.jetbrains', 'org.mvplugins.multiverse.external.jetbrains'
|
||||
relocate 'io.papermc.lib', 'org.mvplugins.multiverse.external.paperlib'
|
||||
|
||||
configurations = [project.configurations.shadowed]
|
||||
|
||||
archiveFileName = "$baseName-$version.$extension"
|
||||
|
||||
dependencies {
|
||||
exclude(dependency {
|
||||
it.moduleGroup == 'org.jetbrains.kotlin'
|
||||
})
|
||||
}
|
||||
//classifier = ''
|
||||
}
|
||||
|
||||
build.dependsOn shadowJar
|
||||
jar.enabled = false
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
|
||||
testLogging {
|
||||
exceptionFormat = 'full'
|
||||
}
|
||||
}
|
||||
@@ -1,364 +0,0 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import groovy.util.Node
|
||||
import groovy.util.NodeList
|
||||
import org.apache.tools.ant.filters.ReplaceTokens
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.credentials.PasswordCredentials
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.tasks.SourceSetContainer
|
||||
import org.gradle.api.tasks.Sync
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.api.tasks.javadoc.Javadoc
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
||||
import org.gradle.external.javadoc.StandardJavadocDocletOptions
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.language.jvm.tasks.ProcessResources
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
eclipse
|
||||
`maven-publish`
|
||||
id("com.gradleup.shadow") version "8.3.9"
|
||||
kotlin("jvm") version "2.0.21"
|
||||
}
|
||||
|
||||
group = "org.mvplugins.multiverse.core"
|
||||
version = System.getenv("GITHUB_VERSION") ?: "5.3.4.17"
|
||||
description = "Multiverse-Core"
|
||||
|
||||
val sourceSets = extensions.getByType<SourceSetContainer>()
|
||||
|
||||
val serverApi: Configuration by configurations.creating
|
||||
val externalPlugin: Configuration by configurations.creating
|
||||
val shadowed: Configuration by configurations.creating
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
|
||||
maven {
|
||||
url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri("https://repo.onarandombox.com/content/groups/public")
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri("https://hub.spigotmc.org/nexus/content/groups/public/")
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri("https://jitpack.io")
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri("https://repo.minebench.de/")
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri("https://repo.maven.apache.org/maven2/")
|
||||
}
|
||||
|
||||
maven {
|
||||
name = "aikar repo"
|
||||
url = uri("https://repo.aikar.co/content/groups/aikar/")
|
||||
}
|
||||
|
||||
maven {
|
||||
name = "glaremasters repo"
|
||||
url = uri("https://repo.glaremasters.me/repository/towny/")
|
||||
}
|
||||
|
||||
maven {
|
||||
name = "helpchatRepoReleases"
|
||||
url = uri("https://repo.helpch.at/releases/")
|
||||
}
|
||||
|
||||
maven {
|
||||
name = "papermc repo"
|
||||
url = uri("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
|
||||
// Purpur API
|
||||
maven("https://repo.purpurmc.org/snapshots")
|
||||
}
|
||||
|
||||
// Configuration wiring like in the Groovy build
|
||||
configurations["compileOnly"].extendsFrom(serverApi)
|
||||
configurations["runtimeClasspath"].extendsFrom(serverApi)
|
||||
|
||||
configurations["implementation"].extendsFrom(externalPlugin)
|
||||
|
||||
configurations["compileClasspath"].extendsFrom(shadowed)
|
||||
configurations["testCompileClasspath"].extendsFrom(shadowed)
|
||||
configurations["testRuntimeClasspath"].extendsFrom(shadowed)
|
||||
|
||||
dependencies {
|
||||
// Server API: Purpur 1.19.4
|
||||
serverApi("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT")
|
||||
|
||||
// Economy
|
||||
externalPlugin("com.github.MilkBowl:VaultAPI:1.7.1") {
|
||||
exclude(group = "org.bukkit", module = "bukkit")
|
||||
}
|
||||
|
||||
// PlaceholderAPI
|
||||
externalPlugin("me.clip:placeholderapi:2.11.6")
|
||||
|
||||
// Command Framework
|
||||
shadowed("co.aikar:acf-paper:0.5.1-SNAPSHOT")
|
||||
|
||||
// Config
|
||||
shadowed("io.github.townyadvanced.commentedconfiguration:CommentedConfiguration:1.0.1") {
|
||||
exclude(group = "org.spigotmc", module = "spigot-api")
|
||||
}
|
||||
|
||||
// Utils
|
||||
shadowed("io.vavr:vavr:0.10.4")
|
||||
shadowed("org.glassfish.hk2:hk2-locator:3.0.3")
|
||||
shadowed("org.glassfish.hk2:hk2-inhabitant-generator:3.0.3") {
|
||||
exclude(group = "org.apache.maven", module = "maven-core")
|
||||
}
|
||||
shadowed("com.dumptruckman.minecraft:Logging:1.1.1") {
|
||||
exclude(group = "junit", module = "junit")
|
||||
}
|
||||
shadowed("de.themoep.idconverter:mappings:1.2-SNAPSHOT")
|
||||
shadowed("org.bstats:bstats-bukkit:3.1.0") {
|
||||
exclude(group = "org.bukkit", module = "bukkit")
|
||||
}
|
||||
shadowed("net.minidev:json-smart:2.4.9")
|
||||
shadowed("org.jetbrains:annotations:22.0.0")
|
||||
shadowed("io.papermc:paperlib:1.0.8")
|
||||
|
||||
// Tests
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.21")
|
||||
testImplementation("com.github.seeseemelk:MockBukkit-v1.19:3.1.0")
|
||||
testImplementation("com.googlecode.json-simple:json-simple:1.1.1") {
|
||||
exclude(group = "junit", module = "junit")
|
||||
}
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
||||
testImplementation("com.natpryce:hamkrest:1.8.0.1")
|
||||
testImplementation("org.mockito.kotlin:mockito-kotlin:4.1.0")
|
||||
|
||||
// Annotation Processors
|
||||
annotationProcessor("org.glassfish.hk2:hk2-metadata-generator:3.0.3")
|
||||
testAnnotationProcessor("org.glassfish.hk2:hk2-metadata-generator:3.0.3")
|
||||
}
|
||||
|
||||
java {
|
||||
// Plugin is compiled for Java 17 (GraalVM 17-friendly)
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
val bitlyAccessToken: String = System.getenv("BITLY_ACCESS_TOKEN") ?: "bitly-access-token"
|
||||
|
||||
// === Token-filtered source generation (prepareSource) ===
|
||||
val prepareSource by tasks.registering(Sync::class) {
|
||||
inputs.property("bitlyAccessToken", bitlyAccessToken)
|
||||
from(sourceSets["main"].java)
|
||||
// avoid deprecated buildDir getter
|
||||
into(layout.buildDirectory.dir("src"))
|
||||
filter<ReplaceTokens>(
|
||||
"tokens" to mapOf(
|
||||
"bitly-access-token" to bitlyAccessToken,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// Use ONLY the filtered sources for compileJava (fixes duplicate classes)
|
||||
tasks.named<JavaCompile>("compileJava") {
|
||||
dependsOn(prepareSource)
|
||||
source = prepareSource.get().outputs.files.asFileTree
|
||||
sourceCompatibility = JavaVersion.VERSION_17.toString()
|
||||
targetCompatibility = JavaVersion.VERSION_17.toString()
|
||||
}
|
||||
|
||||
tasks.named<JavaCompile>("compileTestJava") {
|
||||
sourceCompatibility = JavaVersion.VERSION_17.toString()
|
||||
targetCompatibility = JavaVersion.VERSION_17.toString()
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.encoding = "UTF-8"
|
||||
options.compilerArgs.add(
|
||||
"-Aorg.glassfish.hk2.metadata.location=META-INF/hk2-locator/Multiverse-Core",
|
||||
)
|
||||
}
|
||||
|
||||
tasks.withType<Javadoc>().configureEach {
|
||||
(options as StandardJavadocDocletOptions).encoding = "UTF-8"
|
||||
}
|
||||
|
||||
tasks.named<KotlinCompile>("compileTestKotlin") {
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_17)
|
||||
javaParameters.set(true)
|
||||
}
|
||||
}
|
||||
|
||||
// We're not using Kotlin in the plugin itself, just tests!
|
||||
tasks.named<KotlinCompile>("compileKotlin") {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
configurations
|
||||
.filterNot { it.name.startsWith("test") }
|
||||
.forEach {
|
||||
it.exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8")
|
||||
}
|
||||
|
||||
tasks.named<ProcessResources>("processResources") {
|
||||
val props = mapOf("version" to project.version.toString())
|
||||
inputs.properties(props)
|
||||
filteringCharset = "UTF-8"
|
||||
filesMatching("plugin.yml") {
|
||||
expand(props)
|
||||
}
|
||||
// Never up-to-date: tests depend on fresh version expansion
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
tasks.named<Javadoc>("javadoc") {
|
||||
source = sourceSets["main"].allJava
|
||||
classpath = configurations["compileClasspath"]
|
||||
}
|
||||
|
||||
// Removed: configurations["api"].isCanBeResolved = true (deprecated in Gradle 8/9)
|
||||
|
||||
val jarTask = tasks.named<Jar>("jar")
|
||||
val shadowJarTask = tasks.named<ShadowJar>("shadowJar")
|
||||
|
||||
listOf("apiElements", "runtimeElements").forEach { configurationName ->
|
||||
configurations.named(configurationName) {
|
||||
outgoing.artifacts.removeIf { artifact ->
|
||||
artifact.buildDependencies.getDependencies(null).contains(jarTask.get())
|
||||
}
|
||||
outgoing.artifact(shadowJarTask)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named<ShadowJar>("shadowJar") {
|
||||
relocate("co.aikar", "org.mvplugins.multiverse.external.acf")
|
||||
relocate("com.dumptruckman.minecraft.util.Logging", "org.mvplugins.multiverse.core.utils.CoreLogging")
|
||||
relocate("com.dumptruckman.minecraft.util.DebugLog", "org.mvplugins.multiverse.core.utils.DebugFileLogger")
|
||||
relocate("de.themoep.idconverter", "org.mvplugins.multiverse.external.idconverter")
|
||||
relocate("io.github.townyadvanced.commentedconfiguration", "org.mvplugins.multiverse.external.commentedconfiguration")
|
||||
relocate("me.main__.util", "org.mvplugins.multiverse.external.serializationconfig")
|
||||
relocate("org.bstats", "org.mvplugins.multiverse.external.bstats")
|
||||
relocate("com.sun", "org.mvplugins.multiverse.external.sun")
|
||||
relocate("net.minidev", "org.mvplugins.multiverse.external.minidev")
|
||||
relocate("org.objectweb", "org.mvplugins.multiverse.external.objectweb")
|
||||
relocate("io.vavr", "org.mvplugins.multiverse.external.vavr")
|
||||
relocate("jakarta", "org.mvplugins.multiverse.external.jakarta")
|
||||
relocate("javassist", "org.mvplugins.multiverse.external.javassist")
|
||||
relocate("org.aopalliance", "org.mvplugins.multiverse.external.aopalliance")
|
||||
relocate("org.glassfish", "org.mvplugins.multiverse.external.glassfish")
|
||||
relocate("org.jvnet", "org.mvplugins.multiverse.external.jvnet")
|
||||
relocate("org.intellij", "org.mvplugins.multiverse.external.intellij")
|
||||
relocate("org.jetbrains", "org.mvplugins.multiverse.external.jetbrains")
|
||||
relocate("io.papermc.lib", "org.mvplugins.multiverse.external.paperlib")
|
||||
|
||||
configurations = listOf(project.configurations["shadowed"])
|
||||
|
||||
archiveClassifier.set("")
|
||||
|
||||
dependencies {
|
||||
exclude { dependency ->
|
||||
dependency.moduleGroup == "org.jetbrains.kotlin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("build") {
|
||||
dependsOn("shadowJar")
|
||||
}
|
||||
|
||||
tasks.named<Jar>("jar") {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
tasks.named<Test>("test") {
|
||||
useJUnitPlatform()
|
||||
testLogging {
|
||||
exceptionFormat = TestExceptionFormat.FULL
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("maven") {
|
||||
from(components["java"])
|
||||
|
||||
pom.withXml {
|
||||
val pomNode = asNode()
|
||||
|
||||
val dependenciesNode = (
|
||||
(pomNode.get("dependencies") as? NodeList)
|
||||
?.firstOrNull() as? Node
|
||||
) ?: (pomNode.appendNode("dependencies") as Node)
|
||||
|
||||
val dependencyNodes = dependenciesNode.children().filterIsInstance<Node>().toList()
|
||||
|
||||
// Remove Kotlin dependency
|
||||
dependencyNodes
|
||||
.filter { dependencyNode ->
|
||||
val groupIdNodes = dependencyNode.get("groupId") as? NodeList ?: return@filter false
|
||||
val groupId = (groupIdNodes.firstOrNull() as? Node)?.text()
|
||||
groupId == "org.jetbrains.kotlin"
|
||||
}
|
||||
.forEach { dependencyNode ->
|
||||
dependenciesNode.remove(dependencyNode)
|
||||
}
|
||||
|
||||
// Switch runtime deps to provided
|
||||
dependencyNodes.forEach { dependencyNode ->
|
||||
val scopeNodes = dependencyNode.get("scope") as? NodeList ?: return@forEach
|
||||
val scopeNode = scopeNodes.firstOrNull() as? Node ?: return@forEach
|
||||
if (scopeNode.text() == "runtime") {
|
||||
scopeNode.setValue("provided")
|
||||
}
|
||||
}
|
||||
|
||||
// Add server API (Purpur) to pom as provided
|
||||
configurations["serverApi"].allDependencies.forEach { dependency ->
|
||||
val depNode = dependenciesNode.appendNode("dependency")
|
||||
depNode.appendNode("groupId", dependency.group)
|
||||
depNode.appendNode("artifactId", dependency.name)
|
||||
depNode.appendNode("version", dependency.version)
|
||||
depNode.appendNode("scope", "provided")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
name = "GitHubPackages"
|
||||
url = uri("https://maven.pkg.github.com/Multiverse/Multiverse-Core")
|
||||
credentials {
|
||||
username = System.getenv("GITHUB_ACTOR")
|
||||
password = System.getenv("GITHUB_TOKEN")
|
||||
}
|
||||
}
|
||||
maven {
|
||||
name = "multiverse"
|
||||
val releasesRepoUrl = uri("https://repo.dumptruckman.com/multiverse-releases")
|
||||
val snapshotsRepoUrl = uri("https://repo.dumptruckman.com/multiverse-snapshots")
|
||||
url = if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl
|
||||
credentials(PasswordCredentials::class)
|
||||
}
|
||||
|
||||
maven {
|
||||
// todo: remove before mv5 release
|
||||
name = "multiverseBeta"
|
||||
url = uri("https://repo.c0ding.party/multiverse-beta")
|
||||
credentials(PasswordCredentials::class)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
out.txt
|
||||
@@ -1,20 +0,0 @@
|
||||
filepath = "../src/main/resources/multiverse-core_en.properties"
|
||||
|
||||
enumList = []
|
||||
|
||||
with open(filepath) as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if len(line) == 0:
|
||||
enumList.append("")
|
||||
elif line.startswith("#"):
|
||||
enumList.append(line.replace("#", "//"))
|
||||
else:
|
||||
parts = line.split("=")
|
||||
if (len(parts) < 2):
|
||||
continue
|
||||
parts = parts[0].split(".")[1:]
|
||||
enumList.append("_".join([p.upper() for p in parts]) + ",")
|
||||
|
||||
with open("out.txt", "w") as f:
|
||||
f.write("\n".join(enumList))
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 166 KiB |
@@ -134,7 +134,7 @@
|
||||
<module name="MutableException"/>
|
||||
<module name="OneTopLevelClass"/>
|
||||
<module name="ThrowsCount">
|
||||
<property name="max" value="2"/>
|
||||
<property name="max" value="0"/>
|
||||
</module>
|
||||
<module name="VisibilityModifier">
|
||||
<property name="protectedAllowed" value="true"/>
|
||||
@@ -380,7 +380,7 @@
|
||||
<property name="throwsIndent" value="8"/>
|
||||
<property name="arrayInitIndent" value="4"/>
|
||||
<property name="lineWrappingIndentation" value="8"/>
|
||||
<property name="forceStrictCondition" value="false"/>
|
||||
<property name="forceStrictCondition" value="true"/>
|
||||
</module>
|
||||
<module name="NoCodeInFile"/>
|
||||
<module name="OuterTypeFilename"/>
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+1
-2
@@ -1,7 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -15,8 +15,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -57,7 +55,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -85,9 +83,10 @@ done
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -134,13 +133,10 @@ location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
@@ -148,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
@@ -156,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
@@ -201,15 +197,11 @@ if "$cygwin" || "$msys" ; then
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
|
||||
Vendored
+10
-12
@@ -13,8 +13,6 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@@ -45,11 +43,11 @@ set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -59,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
|
||||
pluginManagement {
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = 'multiverse-core'
|
||||
@@ -1,11 +0,0 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
maven {
|
||||
url = uri("https://repo.onarandombox.com/multiverse-releases")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "Multiverse-Core"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package co.aikar.commands;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
/**
|
||||
* Exists just so we can extend BukkitCommandIssuer since it has a package-private constructor.
|
||||
*/
|
||||
public abstract class OpenBukkitCommandIssuer extends BukkitCommandIssuer {
|
||||
|
||||
protected OpenBukkitCommandIssuer(BukkitCommandManager manager, CommandSender sender) {
|
||||
super(manager, sender);
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
package org.mvplugins.multiverse.core;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.inject.Inject;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.AdvancedPie;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
import org.bukkit.World;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.utils.REPatterns;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
|
||||
/**
|
||||
* Helper class that registers and sends metrics to <a href="https://bstats.org">bstats website</a>.
|
||||
*/
|
||||
@Service
|
||||
final class BstatsMetricsConfigurator {
|
||||
|
||||
private static final int PLUGIN_ID = 7765;
|
||||
private static final String NO_GENERATOR_NAME = "N/A";
|
||||
|
||||
private final WorldManager worldManager;
|
||||
private final Metrics metrics;
|
||||
|
||||
@Inject
|
||||
private BstatsMetricsConfigurator(MultiverseCore plugin, WorldManager worldManager) {
|
||||
this.worldManager = worldManager;
|
||||
this.metrics = new Metrics(plugin, PLUGIN_ID);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void initMetrics() {
|
||||
try {
|
||||
addCustomGeneratorsMetric();
|
||||
addEnvironmentsMetric();
|
||||
addWorldCountMetric();
|
||||
|
||||
Logging.fine("Metrics enabled.");
|
||||
} catch (Exception e) {
|
||||
Logging.warning("There was an issue while enabling metrics:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void addCustomGeneratorsMetric() {
|
||||
addAdvancedPieMetric("custom_generators", map -> {
|
||||
for (MultiverseWorld w : worldManager.getLoadedWorlds()) {
|
||||
incrementCount(map, getGeneratorName(w));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String getGeneratorName(MultiverseWorld world) {
|
||||
String gen = world.getGenerator();
|
||||
return (gen != null && !gen.equalsIgnoreCase("null"))
|
||||
? REPatterns.COLON.split(gen)[0]
|
||||
: NO_GENERATOR_NAME;
|
||||
}
|
||||
|
||||
private void addEnvironmentsMetric() {
|
||||
addAdvancedPieMetric("environments", map -> {
|
||||
for (MultiverseWorld w : worldManager.getLoadedWorlds()) {
|
||||
incrementCount(map, titleCaseEnv(w.getEnvironment()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String titleCaseEnv(World.Environment env) {
|
||||
String envName = env.name().replaceAll("_+", " ");
|
||||
return WordUtils.capitalizeFully(envName);
|
||||
}
|
||||
|
||||
private void addWorldCountMetric() {
|
||||
addLineMetric("worlds", () -> worldManager.getWorlds().size());
|
||||
}
|
||||
|
||||
private void addAdvancedPieMetric(String chartId, Consumer<Map<String, Integer>> metricsFunc) {
|
||||
metrics.addCustomChart(createAdvancedPieChart(chartId, metricsFunc));
|
||||
}
|
||||
|
||||
private void addLineMetric(String chartId, Callable<Integer> metricsFunc) {
|
||||
metrics.addCustomChart(createLineChart(chartId, metricsFunc));
|
||||
}
|
||||
|
||||
private void incrementCount(Map<String, Integer> map, String key) {
|
||||
Integer count = map.getOrDefault(key, 0);
|
||||
map.put(key, count + 1);
|
||||
}
|
||||
|
||||
private AdvancedPie createAdvancedPieChart(String chartId, Consumer<Map<String, Integer>> metricsFunc) {
|
||||
Map<String, Integer> map = new HashMap<>();
|
||||
metricsFunc.accept(map);
|
||||
return new AdvancedPie(chartId, () -> map);
|
||||
}
|
||||
|
||||
private SingleLineChart createLineChart(String chartId, Callable<Integer> metricsFunc) {
|
||||
return new SingleLineChart(chartId, metricsFunc);
|
||||
}
|
||||
}
|
||||
@@ -7,51 +7,73 @@
|
||||
|
||||
package org.mvplugins.multiverse.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import me.main__.util.SerializationConfig.SerializationConfig;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
||||
import org.glassfish.hk2.api.MultiException;
|
||||
import org.glassfish.hk2.api.ServiceHandle;
|
||||
import org.glassfish.hk2.api.ServiceLocator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.anchor.AnchorManager;
|
||||
import org.mvplugins.multiverse.core.destination.Destination;
|
||||
import org.mvplugins.multiverse.core.api.Destination;
|
||||
import org.mvplugins.multiverse.core.api.MVCore;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.commandtools.PluginLocales;
|
||||
import org.mvplugins.multiverse.core.config.MVCoreConfig;
|
||||
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
|
||||
import org.mvplugins.multiverse.core.commands.CoreCommand;
|
||||
import org.mvplugins.multiverse.core.config.CoreConfig;
|
||||
import org.mvplugins.multiverse.core.economy.MVEconomist;
|
||||
import org.mvplugins.multiverse.core.listeners.CoreListener;
|
||||
import org.mvplugins.multiverse.core.inject.PluginServiceLocatorFactory;
|
||||
import org.mvplugins.multiverse.core.module.MultiverseModule;
|
||||
import org.mvplugins.multiverse.core.utils.StringFormatter;
|
||||
import org.mvplugins.multiverse.core.inject.InjectableListener;
|
||||
import org.mvplugins.multiverse.core.inject.PluginInjection;
|
||||
import org.mvplugins.multiverse.core.placeholders.MultiverseCorePlaceholders;
|
||||
import org.mvplugins.multiverse.core.utils.TestingMode;
|
||||
import org.mvplugins.multiverse.core.utils.metrics.MetricsConfigurator;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.location.NullSpawnLocation;
|
||||
import org.mvplugins.multiverse.core.world.location.SpawnLocation;
|
||||
import org.mvplugins.multiverse.core.world.location.UnloadedWorldLocation;
|
||||
import org.mvplugins.multiverse.core.world.config.NullLocation;
|
||||
import org.mvplugins.multiverse.core.world.config.SpawnLocation;
|
||||
|
||||
/**
|
||||
* The start of the Multiverse-Core plugin
|
||||
* The implementation of the Multiverse-{@link MVCore}.
|
||||
*/
|
||||
@Service
|
||||
public class MultiverseCore extends MultiverseModule {
|
||||
public class MultiverseCore extends JavaPlugin implements MVCore {
|
||||
private static final int PROTOCOL = 50;
|
||||
|
||||
private ServiceLocator serviceLocator;
|
||||
@Inject
|
||||
private Provider<CoreConfig> configProvider;
|
||||
private Provider<MVCoreConfig> configProvider;
|
||||
@Inject
|
||||
private Provider<WorldManager> worldManagerProvider;
|
||||
@Inject
|
||||
private Provider<AnchorManager> anchorManagerProvider;
|
||||
@Inject
|
||||
private Provider<MVCommandManager> commandManagerProvider;
|
||||
@Inject
|
||||
private Provider<DestinationsProvider> destinationsProviderProvider;
|
||||
@Inject
|
||||
private Provider<BstatsMetricsConfigurator> metricsConfiguratorProvider;
|
||||
private Provider<MetricsConfigurator> metricsConfiguratorProvider;
|
||||
@Inject
|
||||
private Provider<MVEconomist> economistProvider;
|
||||
@Inject
|
||||
private Provider<PluginLocales> pluginLocalesProvider;
|
||||
|
||||
// Counter for the number of plugins that have registered with us
|
||||
private int pluginCount;
|
||||
|
||||
/**
|
||||
* This is the constructor for the MultiverseCore.
|
||||
@@ -73,9 +95,9 @@ public class MultiverseCore extends MultiverseModule {
|
||||
}
|
||||
|
||||
// Register our config classes
|
||||
ConfigurationSerialization.registerClass(NullSpawnLocation.class);
|
||||
SerializationConfig.initLogging(Logging.getLogger());
|
||||
ConfigurationSerialization.registerClass(NullLocation.class);
|
||||
ConfigurationSerialization.registerClass(SpawnLocation.class);
|
||||
ConfigurationSerialization.registerClass(UnloadedWorldLocation.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,13 +105,11 @@ public class MultiverseCore extends MultiverseModule {
|
||||
*/
|
||||
@Override
|
||||
public void onEnable() {
|
||||
super.onEnable();
|
||||
initializeDependencyInjection(new MultiverseCorePluginBinder(this));
|
||||
initializeDependencyInjection();
|
||||
|
||||
// Load our configs first as we need them for everything else.
|
||||
var config = configProvider.get();
|
||||
var loadSuccess = config.load().andThenTry(config::save).isSuccess();
|
||||
if (!loadSuccess || !config.isLoaded()) {
|
||||
if (!config.isLoaded()) {
|
||||
Logging.severe("Your configs were not loaded.");
|
||||
Logging.severe("Please check your configs and restart the server.");
|
||||
this.getServer().getPluginManager().disablePlugin(this);
|
||||
@@ -99,15 +119,17 @@ public class MultiverseCore extends MultiverseModule {
|
||||
|
||||
// Initialize the worlds
|
||||
worldManagerProvider.get().initAllWorlds().andThenTry(() -> {
|
||||
loadEconomist(); // Setup economy here so vault is loaded
|
||||
// Setup economy here so vault is loaded
|
||||
loadEconomist();
|
||||
|
||||
// Init all the other stuff
|
||||
loadAnchors();
|
||||
registerDynamicListeners(CoreListener.class);
|
||||
registerEvents();
|
||||
setUpLocales();
|
||||
registerCommands(CoreCommand.class);
|
||||
registerCommands();
|
||||
registerDestinations();
|
||||
setupMetrics();
|
||||
loadPlaceholderApiIntegration();
|
||||
loadApiService();
|
||||
saveAllConfigs();
|
||||
logEnableMessage();
|
||||
}).onFailure(e -> {
|
||||
@@ -122,13 +144,30 @@ public class MultiverseCore extends MultiverseModule {
|
||||
*/
|
||||
@Override
|
||||
public void onDisable() {
|
||||
super.onDisable();
|
||||
MultiverseCoreApi.shutdown();
|
||||
saveAllConfigs();
|
||||
shutdownDependencyInjection();
|
||||
PluginServiceLocatorFactory.get().shutdown();
|
||||
Logging.shutdown();
|
||||
}
|
||||
|
||||
private void initializeDependencyInjection() {
|
||||
serviceLocator = PluginInjection.createServiceLocator(new MultiverseCorePluginBinder(this))
|
||||
.andThenTry(locator -> {
|
||||
PluginInjection.enable(this, locator);
|
||||
})
|
||||
.getOrElseThrow(exception -> {
|
||||
Logging.severe("Failed to initialize dependency injection");
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
return new RuntimeException(exception);
|
||||
});
|
||||
}
|
||||
|
||||
private void shutdownDependencyInjection() {
|
||||
if (serviceLocator != null) {
|
||||
PluginInjection.disable(this, serviceLocator);
|
||||
serviceLocator = null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldShowConfig() {
|
||||
return !configProvider.get().getSilentStart();
|
||||
}
|
||||
@@ -143,13 +182,60 @@ public class MultiverseCore extends MultiverseModule {
|
||||
|
||||
private void loadAnchors() {
|
||||
Try.of(() -> anchorManagerProvider.get())
|
||||
.flatMap(AnchorManager::loadAnchors)
|
||||
.onSuccess(AnchorManager::loadAnchors)
|
||||
.onFailure(e -> {
|
||||
Logging.severe("Failed to load anchors");
|
||||
e.printStackTrace();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to Register all the Events needed.
|
||||
*/
|
||||
private void registerEvents() {
|
||||
var pluginManager = getServer().getPluginManager();
|
||||
|
||||
Try.run(() -> serviceLocator.getAllServices(InjectableListener.class).forEach(
|
||||
listener -> pluginManager.registerEvents(listener, this)))
|
||||
.onFailure(e -> {
|
||||
throw new RuntimeException("Failed to register listeners. Terminating...", e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Multiverse-Core commands to Command Manager.
|
||||
*/
|
||||
private void registerCommands() {
|
||||
Try.of(() -> commandManagerProvider.get())
|
||||
.andThenTry(commandManager -> {
|
||||
serviceLocator.getAllServices(MultiverseCommand.class)
|
||||
.forEach(commandManager::registerCommand);
|
||||
})
|
||||
.onFailure(e -> {
|
||||
Logging.severe("Failed to register commands");
|
||||
e.printStackTrace();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register locales.
|
||||
*/
|
||||
private void setUpLocales() {
|
||||
Try.of(() -> commandManagerProvider.get())
|
||||
.andThen(commandManager -> {
|
||||
commandManager.usePerIssuerLocale(true, true);
|
||||
})
|
||||
.mapTry(commandManager -> pluginLocalesProvider.get())
|
||||
.andThen(pluginLocales -> {
|
||||
pluginLocales.addFileResClassLoader(this);
|
||||
pluginLocales.addMessageBundles("multiverse-core");
|
||||
})
|
||||
.onFailure(e -> {
|
||||
Logging.severe("Failed to register locales");
|
||||
e.printStackTrace();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all the destinations.
|
||||
*/
|
||||
@@ -182,12 +268,21 @@ public class MultiverseCore extends MultiverseModule {
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup placeholder api hook
|
||||
* Logs the enable message.
|
||||
*/
|
||||
private void logEnableMessage() {
|
||||
Logging.config("Version %s (API v%s) Enabled - By %s", this.getDescription().getVersion(), PROTOCOL, getAuthors());
|
||||
|
||||
if (configProvider.get().isShowingDonateMessage()) {
|
||||
Logging.config("Help dumptruckman keep this project alive. Become a patron! https://www.patreon.com/dumptruckman");
|
||||
Logging.config("One time donations are also appreciated: https://www.paypal.me/dumptruckman");
|
||||
}
|
||||
}
|
||||
|
||||
private void loadPlaceholderApiIntegration() {
|
||||
if (configProvider.get().isRegisterPapiHook()
|
||||
&& getServer().getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||
Try.run(() -> serviceLocator.getService(PlaceholderExpansionHook.class))
|
||||
Try.run(() -> serviceLocator.createAndInitialize(MultiverseCorePlaceholders.class))
|
||||
.onFailure(e -> {
|
||||
Logging.severe("Failed to load PlaceholderAPI integration.");
|
||||
e.printStackTrace();
|
||||
@@ -196,67 +291,53 @@ public class MultiverseCore extends MultiverseModule {
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the api service for {@link MultiverseCoreApi}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private void loadApiService() {
|
||||
Try.run(() -> MultiverseCoreApi.init(this))
|
||||
.onSuccess(ignore -> Logging.info("API service loaded!"))
|
||||
.onFailure(e -> {
|
||||
Logging.severe("Failed to load API service!");
|
||||
e.printStackTrace();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Save config.yml, worlds.yml, and anchors.yml.
|
||||
*
|
||||
* @return {@link Try#isSuccess()} true if all configs were successfully saved
|
||||
*/
|
||||
private Try<Void> saveAllConfigs() {
|
||||
return configProvider.get().save()
|
||||
.andThenTry(() -> worldManagerProvider.get().saveWorldsConfig())
|
||||
.andThenTry(() -> anchorManagerProvider.get().saveAllAnchors())
|
||||
.onFailure(e ->
|
||||
Logging.severe("Failed to save all configs, things may not work as expected. %s",
|
||||
e.getLocalizedMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the enable message.
|
||||
*/
|
||||
private void logEnableMessage() {
|
||||
Logging.config("\u001B[32mVersion %s (API v%s) Enabled - By %s\u001B[39m",
|
||||
this.getDescription().getVersion(), getVersionAsNumber(), StringFormatter.joinAnd(getDescription().getAuthors()));
|
||||
|
||||
if (configProvider.get().isShowingDonateMessage()) {
|
||||
Logging.config("\u001B[32mLoving Multiverse-Core? Please consider supporting the project with a small donation: https://github.com/sponsors/Multiverse\u001B[39m");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MultiverseCoreApi
|
||||
*
|
||||
* @return The MultiverseCoreApi
|
||||
*
|
||||
* @deprecated Use {@link MultiverseCoreApi#get()} directly.
|
||||
*/
|
||||
@Deprecated(since = "5.1", forRemoval = true)
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.0")
|
||||
public MultiverseCoreApi getApi() {
|
||||
return MultiverseCoreApi.get();
|
||||
@Override
|
||||
public MVCore getCore() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public double getTargetCoreVersion() {
|
||||
return getVersionAsNumber();
|
||||
public int getProtocolVersion() {
|
||||
return PROTOCOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getAuthors() {
|
||||
List<String> authorsList = this.getDescription().getAuthors();
|
||||
if (authorsList.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder authors = new StringBuilder();
|
||||
authors.append(authorsList.get(0));
|
||||
|
||||
for (int i = 1; i < authorsList.size(); i++) {
|
||||
if (i == authorsList.size() - 1) {
|
||||
authors.append(" and ").append(authorsList.get(i));
|
||||
} else {
|
||||
authors.append(", ").append(authorsList.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
return authors.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int getPluginCount() {
|
||||
return this.pluginCount;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
@@ -267,33 +348,78 @@ public class MultiverseCore extends MultiverseModule {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull FileConfiguration getConfig() {
|
||||
CoreConfig coreConfig = this.configProvider.get();
|
||||
var config = coreConfig.getConfig();
|
||||
if (config != null && coreConfig.isLoaded()) {
|
||||
return config;
|
||||
}
|
||||
|
||||
var loadSuccess = coreConfig.load().isSuccess();
|
||||
if (!loadSuccess || !coreConfig.isLoaded()) {
|
||||
throw new RuntimeException("Failed to load configs");
|
||||
}
|
||||
return coreConfig.getConfig();
|
||||
public void incrementPluginCount() {
|
||||
this.pluginCount += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void reloadConfig() {
|
||||
this.configProvider.get().load();
|
||||
public void decrementPluginCount() {
|
||||
this.pluginCount -= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void saveConfig() {
|
||||
this.configProvider.get().save();
|
||||
public boolean saveAllConfigs() {
|
||||
// TODO: Make this all Try<Void>
|
||||
return configProvider.get().save().isSuccess()
|
||||
&& worldManagerProvider.get().saveWorldsConfig()
|
||||
&& anchorManagerProvider.get().saveAnchors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the best service from this plugin that implements the given contract or has the given implementation.
|
||||
*
|
||||
* @param contractOrImpl The contract or concrete implementation to get the best instance of
|
||||
* @param qualifiers The set of qualifiers that must match this service definition
|
||||
* @param <T> The type of the contract to get
|
||||
* @return An instance of the contract or impl if it is a service and is already instantiated, null otherwise
|
||||
* @throws MultiException if there was an error during service lookup
|
||||
*/
|
||||
@Nullable
|
||||
public <T> T getService(@NotNull Class<T> contractOrImpl, Annotation... qualifiers) throws MultiException {
|
||||
var handle = serviceLocator.getServiceHandle(contractOrImpl, qualifiers);
|
||||
if (handle != null && handle.isActive()) {
|
||||
return handle.getService();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all services from this plugin that implement the given contract or have the given implementation and have
|
||||
* the provided qualifiers.
|
||||
*
|
||||
* @param contractOrImpl The contract or concrete implementation to get the best instance of
|
||||
* @param qualifiers The set of qualifiers that must match this service definition
|
||||
* @param <T> The type of the contract to get
|
||||
* @return A list of services implementing this contract or concrete implementation. May not return null, but may
|
||||
* return an empty list.
|
||||
* @throws MultiException if there was an error during service lookup
|
||||
*/
|
||||
@NotNull
|
||||
public <T> List<T> getAllServices(
|
||||
@NotNull Class<T> contractOrImpl,
|
||||
Annotation... qualifiers) throws MultiException {
|
||||
var handles = serviceLocator.getAllServiceHandles(contractOrImpl, qualifiers);
|
||||
return handles.stream()
|
||||
.filter(ServiceHandle::isActive)
|
||||
.map(ServiceHandle::getService)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* This is for unit testing ONLY. Do not use this constructor.
|
||||
*
|
||||
* @param loader The PluginLoader to use.
|
||||
* @param description The Description file to use.
|
||||
* @param dataFolder The folder that other datafiles can be found in.
|
||||
* @param file The location of the plugin.
|
||||
*/
|
||||
public MultiverseCore(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) {
|
||||
super(loader, description, dataFolder, file);
|
||||
}
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
package org.mvplugins.multiverse.core;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.mvplugins.multiverse.core.anchor.AnchorManager;
|
||||
import org.mvplugins.multiverse.core.config.CoreConfig;
|
||||
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
|
||||
import org.mvplugins.multiverse.core.economy.MVEconomist;
|
||||
import org.mvplugins.multiverse.core.inject.PluginServiceLocator;
|
||||
import org.mvplugins.multiverse.core.teleportation.AsyncSafetyTeleporter;
|
||||
import org.mvplugins.multiverse.core.teleportation.BlockSafety;
|
||||
import org.mvplugins.multiverse.core.teleportation.LocationManipulation;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.biomeprovider.BiomeProviderFactory;
|
||||
import org.mvplugins.multiverse.core.world.generators.GeneratorProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Provides access to the MultiverseCore API.
|
||||
*/
|
||||
public class MultiverseCoreApi {
|
||||
|
||||
private static MultiverseCoreApi instance;
|
||||
private static final List<Consumer<MultiverseCoreApi>> whenLoadedCallbacks = new ArrayList<>();
|
||||
|
||||
static void init(@NotNull MultiverseCore multiverseCore) {
|
||||
if (instance != null) {
|
||||
throw new IllegalStateException("MultiverseCoreApi has already been initialized!");
|
||||
}
|
||||
instance = new MultiverseCoreApi(multiverseCore.getServiceLocator());
|
||||
Bukkit.getServicesManager().register(MultiverseCoreApi.class, instance, multiverseCore, ServicePriority.Normal);
|
||||
|
||||
whenLoadedCallbacks.forEach(c -> c.accept(instance));
|
||||
whenLoadedCallbacks.clear();
|
||||
}
|
||||
|
||||
static void shutdown() {
|
||||
Bukkit.getServicesManager().unregister(instance);
|
||||
instance = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook your plugin into the MultiverseCoreApi here to ensure you only start using the API after it has been initialized.
|
||||
* Use this if you know your plugin may load before Multiverse-Core is fully initialized.
|
||||
* <br/>
|
||||
* This handy method removes the need for you to check with plugin manager or listen to plugin enable event.
|
||||
* <br/>
|
||||
* Callback will be called immediately if the MultiverseCoreApi has already been initialized.
|
||||
*
|
||||
* @param consumer The callback to execute when the MultiverseCoreApi has been initialized.
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public static void whenLoaded(@NotNull Consumer<MultiverseCoreApi> consumer) {
|
||||
if (instance != null) {
|
||||
consumer.accept(instance);
|
||||
} else {
|
||||
whenLoadedCallbacks.add(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the MultiverseCoreApi has been initialized.
|
||||
*
|
||||
* @return True if the MultiverseCoreApi has been initialized, false otherwise
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public static boolean isLoaded() {
|
||||
return instance != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MultiverseCoreApi. This will throw an exception if the Multiverse-Core has not been initialized.
|
||||
* <br/>
|
||||
* You can check if the MultiverseCoreApi has been initialized with {@link #isLoaded()} before using this method.
|
||||
* <br/>
|
||||
* Alternatively, you can use {@link #whenLoaded(Consumer)} to hook into the MultiverseCoreApi if your plugin may
|
||||
* load before Multiverse-Core is fully initialized.
|
||||
*
|
||||
* @return The MultiverseCoreApi
|
||||
* @throws IllegalStateException if the MultiverseCoreApi has not been initialized
|
||||
*/
|
||||
public static @NotNull MultiverseCoreApi get() {
|
||||
if (instance == null) {
|
||||
throw new IllegalStateException("MultiverseCoreApi has not been initialized!");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final PluginServiceLocator serviceLocator;
|
||||
|
||||
private MultiverseCoreApi(@NotNull PluginServiceLocator serviceProvider) {
|
||||
this.serviceLocator = serviceProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of AnchorManager.
|
||||
*
|
||||
* @return The AnchorManager instance
|
||||
*/
|
||||
public @NotNull AnchorManager getAnchorManager() {
|
||||
return Objects.requireNonNull(serviceLocator.getActiveService(AnchorManager.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of BiomeProviderFactory.
|
||||
*
|
||||
* @return The BiomeProviderFactory instance
|
||||
*/
|
||||
public @NotNull BiomeProviderFactory getBiomeProviderFactory() {
|
||||
return Objects.requireNonNull(serviceLocator.getActiveService(BiomeProviderFactory.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of BlockSafety.
|
||||
*
|
||||
* @return The BlockSafety instance
|
||||
*/
|
||||
public @NotNull BlockSafety getBlockSafety() {
|
||||
return Objects.requireNonNull(serviceLocator.getActiveService(BlockSafety.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of CoreConfig.
|
||||
*
|
||||
* @return The CoreConfig instance
|
||||
*/
|
||||
public @NotNull CoreConfig getCoreConfig() {
|
||||
return Objects.requireNonNull(serviceLocator.getActiveService(CoreConfig.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of DestinationsProvider.
|
||||
*
|
||||
* @return The DestinationsProvider instance
|
||||
*/
|
||||
public @NotNull DestinationsProvider getDestinationsProvider() {
|
||||
return Objects.requireNonNull(serviceLocator.getActiveService(DestinationsProvider.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of GeneratorProvider.
|
||||
*
|
||||
* @return The GeneratorProvider instance
|
||||
*/
|
||||
public @NotNull GeneratorProvider getGeneratorProvider() {
|
||||
return Objects.requireNonNull(serviceLocator.getActiveService(GeneratorProvider.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of LocationManipulation.
|
||||
*
|
||||
* @return The LocationManipulation instance
|
||||
*/
|
||||
public @NotNull LocationManipulation getLocationManipulation() {
|
||||
return Objects.requireNonNull(serviceLocator.getActiveService(LocationManipulation.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of MVEconomist.
|
||||
*
|
||||
* @return The MVEconomist instance
|
||||
*/
|
||||
public @NotNull MVEconomist getMVEconomist() {
|
||||
return Objects.requireNonNull(serviceLocator.getActiveService(MVEconomist.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of SafetyTeleporter.
|
||||
*
|
||||
* @return The SafetyTeleporter instance
|
||||
*/
|
||||
public @NotNull AsyncSafetyTeleporter getSafetyTeleporter() {
|
||||
return Objects.requireNonNull(serviceLocator.getActiveService(AsyncSafetyTeleporter.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of WorldManager.
|
||||
*
|
||||
* @return The WorldManager instance
|
||||
*/
|
||||
public @NotNull WorldManager getWorldManager() {
|
||||
return Objects.requireNonNull(serviceLocator.getActiveService(WorldManager.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of Multiverse-Core's PluginServiceLocator.
|
||||
* <br/>
|
||||
* You can use this to hook into the hk2 dependency injection system used by Multiverse-Core.
|
||||
*
|
||||
* @return The Multiverse-Core's PluginServiceLocator
|
||||
*/
|
||||
public @NotNull PluginServiceLocator getServiceLocator() {
|
||||
return serviceLocator;
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,18 @@ package org.mvplugins.multiverse.core;
|
||||
import org.glassfish.hk2.utilities.binding.ScopedBindingBuilder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.mvplugins.multiverse.core.module.MultiverseModuleBinder;
|
||||
import org.mvplugins.multiverse.core.api.MVCore;
|
||||
import org.mvplugins.multiverse.core.inject.binder.JavaPluginBinder;
|
||||
|
||||
final class MultiverseCorePluginBinder extends MultiverseModuleBinder<MultiverseCore> {
|
||||
class MultiverseCorePluginBinder extends JavaPluginBinder<MultiverseCore> {
|
||||
|
||||
MultiverseCorePluginBinder(@NotNull MultiverseCore plugin) {
|
||||
protected MultiverseCorePluginBinder(@NotNull MultiverseCore plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ScopedBindingBuilder<MultiverseCore> bindPluginClass(
|
||||
ScopedBindingBuilder<MultiverseCore> bindingBuilder) {
|
||||
return super.bindPluginClass(bindingBuilder).to(MultiverseCore.class);
|
||||
return super.bindPluginClass(bindingBuilder).to(MVCore.class).to(MultiverseCore.class);
|
||||
}
|
||||
}
|
||||
@@ -8,14 +8,14 @@
|
||||
package org.mvplugins.multiverse.core.anchor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import io.vavr.control.Option;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
@@ -23,183 +23,167 @@ import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.MultiverseCore;
|
||||
import org.mvplugins.multiverse.core.teleportation.LocationManipulation;
|
||||
import org.mvplugins.multiverse.core.utils.result.Result;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.entrycheck.WorldEntryCheckerProvider;
|
||||
import org.mvplugins.multiverse.core.world.location.UnloadedWorldLocation;
|
||||
import org.mvplugins.multiverse.core.api.LocationManipulation;
|
||||
import org.mvplugins.multiverse.core.config.MVCoreConfig;
|
||||
|
||||
/**
|
||||
* Manages anchors and it's location.
|
||||
* Manages anchors.
|
||||
*/
|
||||
@Service
|
||||
public final class AnchorManager {
|
||||
|
||||
private static final String ANCHORS_FILE = "anchors.yml";
|
||||
private static final String ANCHORS_CONFIG_SECTION = "anchors";
|
||||
|
||||
private final Map<String, MultiverseAnchor> anchors;
|
||||
public class AnchorManager {
|
||||
private Map<String, Location> anchors;
|
||||
private FileConfiguration anchorConfig;
|
||||
|
||||
private final Plugin plugin;
|
||||
private final LocationManipulation locationManipulation;
|
||||
private final WorldEntryCheckerProvider entryCheckerProvider;
|
||||
private final WorldManager worldManager;
|
||||
private final MVCoreConfig config;
|
||||
|
||||
@Inject
|
||||
AnchorManager(
|
||||
public AnchorManager(
|
||||
MultiverseCore plugin,
|
||||
LocationManipulation locationManipulation,
|
||||
WorldEntryCheckerProvider entryCheckerProvider,
|
||||
WorldManager worldManager
|
||||
MVCoreConfig config
|
||||
) {
|
||||
this.plugin = plugin;
|
||||
this.locationManipulation = locationManipulation;
|
||||
this.entryCheckerProvider = entryCheckerProvider;
|
||||
this.worldManager = worldManager;
|
||||
this.config = config;
|
||||
|
||||
this.anchors = new HashMap<>();
|
||||
this.anchors = new HashMap<String, Location>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all anchors.
|
||||
*/
|
||||
public Try<Void> loadAnchors() {
|
||||
anchors.clear();
|
||||
return Try.run(() -> {
|
||||
anchorConfig = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), ANCHORS_FILE));
|
||||
parseAnchorsFromConfig();
|
||||
});
|
||||
}
|
||||
|
||||
private void parseAnchorsFromConfig() {
|
||||
var anchorsSection = getAnchorsConfigSection();
|
||||
public void loadAnchors() {
|
||||
this.anchors = new HashMap<String, Location>();
|
||||
this.anchorConfig = YamlConfiguration.loadConfiguration(new File(this.plugin.getDataFolder(), "anchors.yml"));
|
||||
this.ensureConfigIsPrepared();
|
||||
ConfigurationSection anchorsSection = this.anchorConfig.getConfigurationSection("anchors");
|
||||
Set<String> anchorKeys = anchorsSection.getKeys(false);
|
||||
for (String key : anchorKeys) {
|
||||
//world:x,y,z:pitch:yaw
|
||||
Location anchorLocation = locationManipulation.stringToLocation(anchorsSection.getString(key, ""));
|
||||
Location anchorLocation = this.locationManipulation.stringToLocation(anchorsSection.getString(key, ""));
|
||||
if (anchorLocation != null) {
|
||||
Logging.config("Loading anchor: '%s'...", key);
|
||||
anchors.put(key, new MultiverseAnchor(key, UnloadedWorldLocation.fromLocation(anchorLocation)));
|
||||
this.anchors.put(key, anchorLocation);
|
||||
} else {
|
||||
Logging.warning("The location for anchor '%s' is INVALID.", key);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private ConfigurationSection getAnchorsConfigSection() {
|
||||
var anchorsConfigSection = anchorConfig.getConfigurationSection(ANCHORS_CONFIG_SECTION);
|
||||
if (anchorsConfigSection == null) {
|
||||
anchorsConfigSection = anchorConfig.createSection(ANCHORS_CONFIG_SECTION);
|
||||
private void ensureConfigIsPrepared() {
|
||||
if (this.anchorConfig.getConfigurationSection("anchors") == null) {
|
||||
this.anchorConfig.createSection("anchors");
|
||||
}
|
||||
return anchorsConfigSection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves all anchors.
|
||||
*
|
||||
* @return True if all anchors were successfully saved.
|
||||
*/
|
||||
public Try<Void> saveAllAnchors() {
|
||||
return Try.run(() -> anchorConfig.save(new File(plugin.getDataFolder(), ANCHORS_FILE)))
|
||||
.onFailure(failure ->
|
||||
Logging.severe("Failed to save anchors.yml. Please check your file permissions."));
|
||||
public boolean saveAnchors() {
|
||||
try {
|
||||
this.anchorConfig.save(new File(this.plugin.getDataFolder(), "anchors.yml"));
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Logging.severe("Failed to save anchors.yml. Please check your file permissions.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Location} associated with an anchor.
|
||||
*
|
||||
* @param anchorName The name of the anchor.
|
||||
* @param anchor The name of the anchor.
|
||||
* @return The {@link Location}.
|
||||
*/
|
||||
public Option<MultiverseAnchor> getAnchor(String anchorName) {
|
||||
return Option.of(anchors.get(anchorName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new location for an anchor. Creates a new anchor if it doesn't exist.
|
||||
*
|
||||
* @param anchorName The name of the anchor.
|
||||
* @param location The location of the anchor as string (world:x,y,z:pitch:yaw).
|
||||
* @return True if the anchor was successfully saved.
|
||||
*/
|
||||
public Try<Void> setAnchor(@NotNull String anchorName, @NotNull String location) {
|
||||
Location parsed = locationManipulation.stringToLocation(location);
|
||||
if (parsed == null) {
|
||||
return Try.failure(new IllegalArgumentException("The location for anchor '" + anchorName + "' is INVALID."));
|
||||
public Location getAnchorLocation(String anchor) {
|
||||
if (this.anchors.containsKey(anchor)) {
|
||||
return this.anchors.get(anchor);
|
||||
}
|
||||
return setAnchor(anchorName, parsed);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new location for an anchor. Creates a new anchor if it doesn't exist.
|
||||
*
|
||||
* @param anchorName The name of the anchor.
|
||||
* @param location The {@link Location} of the anchor.
|
||||
* Saves an anchor.
|
||||
* @param anchor The name of the anchor.
|
||||
* @param location The location of the anchor as string.
|
||||
* @return True if the anchor was successfully saved.
|
||||
*/
|
||||
public Try<Void> setAnchor(@NotNull String anchorName, @NotNull Location location) {
|
||||
Option.of(anchors.get(anchorName))
|
||||
.peek(anchor -> anchor.setLocation(UnloadedWorldLocation.fromLocation(location)))
|
||||
.onEmpty(() -> anchors.put(anchorName, new MultiverseAnchor(anchorName, UnloadedWorldLocation.fromLocation(location))));
|
||||
getAnchorsConfigSection().set(anchorName, locationManipulation.locationToString(location));
|
||||
return saveAllAnchors();
|
||||
public boolean saveAnchorLocation(String anchor, String location) {
|
||||
Location parsed = this.locationManipulation.stringToLocation(location);
|
||||
return parsed != null && this.saveAnchorLocation(anchor, parsed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves an anchor.
|
||||
* @param anchor The name of the anchor.
|
||||
* @param l The {@link Location} of the anchor.
|
||||
* @return True if the anchor was successfully saved.
|
||||
*/
|
||||
public boolean saveAnchorLocation(String anchor, Location l) {
|
||||
if (l == null) {
|
||||
return false;
|
||||
}
|
||||
this.anchorConfig.set("anchors." + anchor, this.locationManipulation.locationToString(l));
|
||||
this.anchors.put(anchor, l);
|
||||
return this.saveAnchors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all anchors.
|
||||
*
|
||||
* @return An unmodifiable {@link List} containing all anchors.
|
||||
* @return An unmodifiable {@link Set} containing all anchors.
|
||||
*/
|
||||
public List<MultiverseAnchor> getAllAnchors() {
|
||||
return anchors.values().stream().toList();
|
||||
public Set<String> getAllAnchors() {
|
||||
return Collections.unmodifiableSet(this.anchors.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all anchors that the specified {@link Player} can access.
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @return An unmodifiable {@link List} containing all anchors the specified {@link Player} can access.
|
||||
* @param p The {@link Player}.
|
||||
* @return An unmodifiable {@link Set} containing all anchors the specified {@link Player} can access.
|
||||
*/
|
||||
public List<MultiverseAnchor> getAnchors(@Nullable Player player) {
|
||||
if (player == null) {
|
||||
return getAllAnchors();
|
||||
} else {
|
||||
return getAnchorsForPlayer(player);
|
||||
public Set<String> getAnchors(Player p) {
|
||||
if (p == null) {
|
||||
return this.anchors.keySet();
|
||||
}
|
||||
}
|
||||
|
||||
private List<MultiverseAnchor> getAnchorsForPlayer(@NotNull Player player) {
|
||||
return anchors.values().stream()
|
||||
.filter(anchor -> shouldIncludeAnchorForPlayer(anchor, player))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private boolean shouldIncludeAnchorForPlayer(MultiverseAnchor anchor, Player player) {
|
||||
return worldManager.getWorld(anchor.getLocationWorld())
|
||||
.map(mvWorld -> entryCheckerProvider.forSender(player).canAccessWorld(mvWorld))
|
||||
.peek(result -> Logging.finer("Result for %s can access anchor %s: %s", player.getName(), anchor.getName(), result))
|
||||
.map(Result::isSuccess)
|
||||
.getOrElse(true);
|
||||
Set<String> myAnchors = new HashSet<String>();
|
||||
for (String anchor : this.anchors.keySet()) {
|
||||
Location ancLoc = this.anchors.get(anchor);
|
||||
if (ancLoc == null) {
|
||||
continue;
|
||||
}
|
||||
String worldPerm = "multiverse.access." + ancLoc.getWorld().getName();
|
||||
// Add to the list if we're not enforcing access
|
||||
// OR
|
||||
// We are enforcing access and the user has the permission.
|
||||
if (!config.getEnforceAccess() ||
|
||||
(config.getEnforceAccess() && p.hasPermission(worldPerm))) {
|
||||
myAnchors.add(anchor);
|
||||
} else {
|
||||
Logging.finer(String.format("Not adding anchor %s to the list, user %s doesn't have the %s " +
|
||||
"permission and 'enforceaccess' is enabled!",
|
||||
anchor, p.getName(), worldPerm));
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableSet(myAnchors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the specified anchor.
|
||||
*
|
||||
* @param anchor The anchor to delete.
|
||||
* @param s The name of the anchor.
|
||||
* @return True if the anchor was successfully deleted.
|
||||
*/
|
||||
public Try<Void> deleteAnchor(@NotNull MultiverseAnchor anchor) {
|
||||
if (anchors.containsKey(anchor.getName())) {
|
||||
anchors.remove(anchor.getName());
|
||||
getAnchorsConfigSection().set(anchor.getName(), null);
|
||||
return saveAllAnchors();
|
||||
public boolean deleteAnchor(String s) {
|
||||
if (this.anchors.containsKey(s)) {
|
||||
this.anchors.remove(s);
|
||||
this.anchorConfig.set("anchors." + s, null);
|
||||
return this.saveAnchors();
|
||||
}
|
||||
return Try.failure(new IllegalArgumentException("Anchor does not exist"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.anchor;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.mvplugins.multiverse.core.world.location.UnloadedWorldLocation;
|
||||
|
||||
/**
|
||||
* Represents a single anchor location.
|
||||
*/
|
||||
public final class MultiverseAnchor {
|
||||
|
||||
private final String name;
|
||||
private UnloadedWorldLocation location;
|
||||
|
||||
MultiverseAnchor(String name, UnloadedWorldLocation location) {
|
||||
this.name = name;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the anchor.
|
||||
*
|
||||
* @return The name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a copy of the anchor's location.
|
||||
*
|
||||
* @return The location.
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location.toBukkitLocation();
|
||||
}
|
||||
|
||||
void setLocation(Location location) {
|
||||
this.location = new UnloadedWorldLocation(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world of the anchor's location.
|
||||
*
|
||||
* @return The world.
|
||||
*/
|
||||
@Nullable World getLocationWorld() {
|
||||
if (location == null) {
|
||||
return null;
|
||||
}
|
||||
return location.getWorld();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package org.mvplugins.multiverse.core.api;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Minecart;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
import org.jvnet.hk2.annotations.Contract;
|
||||
|
||||
/**
|
||||
* Used to get block/location-related information.
|
||||
*/
|
||||
@Contract
|
||||
public interface BlockSafety {
|
||||
/**
|
||||
* This function checks whether the block at the given coordinates are above air or not.
|
||||
* @param l The {@link Location} of the block.
|
||||
* @return True if the block at that {@link Location} is above air.
|
||||
*/
|
||||
boolean isBlockAboveAir(Location l);
|
||||
|
||||
/**
|
||||
* Checks if a player can spawn safely at the given coordinates.
|
||||
* @param world The {@link World}.
|
||||
* @param x The x-coordinate.
|
||||
* @param y The y-coordinate.
|
||||
* @param z The z-coordinate.
|
||||
* @return True if a player can spawn safely at the given coordinates.
|
||||
*/
|
||||
boolean playerCanSpawnHereSafely(World world, double x, double y, double z);
|
||||
|
||||
/**
|
||||
* This function checks whether the block at the coordinates given is safe or not by checking for Lava/Fire/Air
|
||||
* etc. This also ensures there is enough space for a player to spawn!
|
||||
*
|
||||
* @param l The {@link Location}
|
||||
* @return Whether the player can spawn safely at the given {@link Location}
|
||||
*/
|
||||
boolean playerCanSpawnHereSafely(Location l);
|
||||
|
||||
/**
|
||||
* Gets a safe bed spawn location OR null if the bed is invalid.
|
||||
* @param l The location of the bead head (block with the pillow on it).
|
||||
* @return Safe location around the bed or null if no location was found.
|
||||
*/
|
||||
Location getSafeBedSpawn(Location l);
|
||||
|
||||
/**
|
||||
* Gets the location of the top block at the specified {@link Location}.
|
||||
* @param l Any {@link Location}.
|
||||
* @return The {@link Location} of the top-block.
|
||||
*/
|
||||
Location getTopBlock(Location l);
|
||||
|
||||
/**
|
||||
* Gets the location of the top block at the specified {@link Location}.
|
||||
* @param l Any {@link Location}.
|
||||
* @return The {@link Location} of the top-block.
|
||||
*/
|
||||
Location getBottomBlock(Location l);
|
||||
|
||||
/**
|
||||
* Checks if an entity would be on track at the specified {@link Location}.
|
||||
* @param l The {@link Location}.
|
||||
* @return True if an entity would be on tracks at the specified {@link Location}.
|
||||
*/
|
||||
boolean isEntitiyOnTrack(Location l);
|
||||
|
||||
/**
|
||||
* Checks if the specified {@link Minecart} can spawn safely.
|
||||
* @param cart The {@link Minecart}.
|
||||
* @return True if the minecart can spawn safely.
|
||||
*/
|
||||
boolean canSpawnCartSafely(Minecart cart);
|
||||
|
||||
/**
|
||||
* Checks if the specified {@link Vehicle} can spawn safely.
|
||||
* @param vehicle The {@link Vehicle}.
|
||||
* @return True if the vehicle can spawn safely.
|
||||
*/
|
||||
boolean canSpawnVehicleSafely(Vehicle vehicle);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.mvplugins.multiverse.core.api;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Contract;
|
||||
|
||||
@Contract
|
||||
public interface Destination<T extends DestinationInstance> {
|
||||
/**
|
||||
* Returns the identifier or prefix that is required for this destination.
|
||||
*
|
||||
* <p>Portals have a prefix of "p" for example and OpenWarp (third party plugin) uses "ow". This is derived from a
|
||||
* hash and cannot have duplicate values. Read that as your plugin cannot use 'p' because it's already used.
|
||||
* Please check the wiki when adding a custom destination!</p>
|
||||
*
|
||||
* @return The identifier or prefix that is required for this destination.
|
||||
*/
|
||||
@NotNull String getIdentifier();
|
||||
|
||||
/**
|
||||
* Returns the destination instance for the given destination parameters.
|
||||
*
|
||||
* @param destinationParams The destination parameters. ex: p:MyPortal:nw
|
||||
* @return The destination instance, or null if the destination parameters are invalid.
|
||||
*/
|
||||
@Nullable T getDestinationInstance(@Nullable String destinationParams);
|
||||
|
||||
/**
|
||||
* Returns a list of possible destinations for the given destination parameters.
|
||||
*
|
||||
* @param issuer The command issuer.
|
||||
* @param destinationParams The destination parameters. ex: p:MyPortal:nw
|
||||
* @return A list of possible destinations.
|
||||
*/
|
||||
@NotNull Collection<String> suggestDestinations(@NotNull BukkitCommandIssuer issuer, @Nullable String destinationParams);
|
||||
|
||||
/**
|
||||
* Should the Multiverse SafeTeleporter be used?
|
||||
*
|
||||
* <p>If not, MV will blindly take people to the location specified.</p>
|
||||
*
|
||||
* @return True if the SafeTeleporter will be used, false if not.
|
||||
*/
|
||||
boolean checkTeleportSafety();
|
||||
|
||||
/**
|
||||
* Returns the teleporter to use for this destination.
|
||||
*
|
||||
* <p>By default, Multiverse will automatically use SafeTeleporter. If you want to use a different teleporter, you can
|
||||
* override this method.</p>
|
||||
*
|
||||
* @return The custom teleporter to use for this destination. Return null to use the default teleporter.
|
||||
*/
|
||||
@Nullable Teleporter getTeleporter();
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.mvplugins.multiverse.core.api;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface DestinationInstance {
|
||||
/**
|
||||
* Gets the exact location to teleport an entity to.
|
||||
*
|
||||
* @param teleportee The entity to teleport.
|
||||
* @return The location to teleport to.
|
||||
*/
|
||||
@Nullable Location getLocation(@NotNull Entity teleportee);
|
||||
|
||||
/**
|
||||
* Gets the velocity to apply to an entity after teleporting.
|
||||
*
|
||||
* @param teleportee The entity to teleport.
|
||||
* @return A vector representing the speed/direction the player should travel when arriving at the destination.
|
||||
*/
|
||||
@Nullable Vector getVelocity(@NotNull Entity teleportee);
|
||||
|
||||
/**
|
||||
* Gets the permission suffix to check for when teleporting to this destination.
|
||||
* This is used for finer per world/player permissions, such as "multiverse.teleport.self.worldname".
|
||||
*
|
||||
* <p>For example, if the destination is "w:world", the permission suffix is "world".</p>
|
||||
*
|
||||
* @return The permission suffix.
|
||||
*/
|
||||
@Nullable String getFinerPermissionSuffix();
|
||||
|
||||
/**
|
||||
* Serialises the destination instance to a savable string.
|
||||
*
|
||||
* <p>This is used when plugins save destinations to configuration,
|
||||
* and when the destination is displayed to the user.</p>
|
||||
*
|
||||
* @return The serialised destination instance.
|
||||
*/
|
||||
@NotNull String serialise();
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.mvplugins.multiverse.core.api;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jvnet.hk2.annotations.Contract;
|
||||
|
||||
/**
|
||||
* Used to manipulate locations.
|
||||
*/
|
||||
@Contract
|
||||
public interface LocationManipulation {
|
||||
/**
|
||||
* Convert a Location into a Colon separated string to allow us to store it in text.
|
||||
* <p>
|
||||
* WORLD:X,Y,Z:yaw:pitch
|
||||
* <p>
|
||||
* The corresponding String2Loc function is {@link #stringToLocation}
|
||||
*
|
||||
* @param location The Location to save.
|
||||
* @return The location as a string in this format: WORLD:x,y,z:yaw:pitch
|
||||
*/
|
||||
String locationToString(Location location);
|
||||
|
||||
/**
|
||||
* This method simply does some rounding, rather than forcing a call to the server to get the blockdata.
|
||||
*
|
||||
* @param l The location to round to the block location
|
||||
* @return A rounded location.
|
||||
*/
|
||||
Location getBlockLocation(Location l);
|
||||
|
||||
/**
|
||||
* Returns a new location from a given string. The format is as follows:
|
||||
* <p>
|
||||
* WORLD:X,Y,Z:yaw:pitch
|
||||
* <p>
|
||||
* The corresponding Location2String function is {@link #stringToLocation}
|
||||
*
|
||||
* @param locationString The location represented as a string (WORLD:X,Y,Z:yaw:pitch)
|
||||
* @return A new location defined by the string or null if the string was invalid.
|
||||
*/
|
||||
Location stringToLocation(String locationString);
|
||||
|
||||
/**
|
||||
* Returns a colored string with the coords.
|
||||
*
|
||||
* @param l The {@link Location}
|
||||
* @return The {@link String}
|
||||
*/
|
||||
String strCoords(Location l);
|
||||
|
||||
/**
|
||||
* Converts a location to a printable readable formatted string including pitch/yaw.
|
||||
*
|
||||
* @param l The {@link Location}
|
||||
* @return The {@link String}
|
||||
*/
|
||||
String strCoordsRaw(Location l);
|
||||
|
||||
/**
|
||||
* Return the NESW Direction a Location is facing.
|
||||
*
|
||||
* @param location The {@link Location}
|
||||
* @return The NESW Direction
|
||||
*/
|
||||
String getDirection(Location location);
|
||||
|
||||
/**
|
||||
* Returns the float yaw position for the given cardinal direction.
|
||||
*
|
||||
* @param orientation The cardinal direction
|
||||
* @return The yaw
|
||||
*/
|
||||
float getYaw(String orientation);
|
||||
|
||||
/**
|
||||
* Returns a speed float from a given vector.
|
||||
*
|
||||
* @param v The {@link Vector}
|
||||
* @return The speed
|
||||
*/
|
||||
float getSpeed(Vector v);
|
||||
|
||||
/**
|
||||
* Returns a translated vector from the given direction.
|
||||
*
|
||||
* @param v The old {@link Vector}
|
||||
* @param direction The new direction
|
||||
* @return The translated {@link Vector}
|
||||
*/
|
||||
Vector getTranslatedVector(Vector v, String direction);
|
||||
|
||||
/**
|
||||
* Returns the next Location that a {@link Vehicle} is traveling at.
|
||||
*
|
||||
* @param v The {@link Vehicle}
|
||||
* @return The {@link Location}
|
||||
*/
|
||||
Location getNextBlock(Vehicle v);
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
package org.mvplugins.multiverse.core.api;
|
||||
|
||||
import io.vavr.control.Try;
|
||||
import org.jvnet.hk2.annotations.Contract;
|
||||
|
||||
import org.mvplugins.multiverse.core.configuration.node.NodeGroup;
|
||||
import org.mvplugins.multiverse.core.placeholders.MultiverseCorePlaceholders;
|
||||
|
||||
@Contract
|
||||
public interface MVConfig {
|
||||
|
||||
/**
|
||||
* Loads the config from disk.
|
||||
* @return True if the config was loaded successfully.
|
||||
*/
|
||||
Try<Void> load();
|
||||
|
||||
/**
|
||||
* Whether the config has been loaded.
|
||||
* @return True if the config has been loaded.
|
||||
*/
|
||||
boolean isLoaded();
|
||||
|
||||
/**
|
||||
* Saves the config to disk.
|
||||
*/
|
||||
Try<Void> save();
|
||||
|
||||
/**
|
||||
* Gets the nodes for the config.
|
||||
*
|
||||
* @return The nodes for the config.
|
||||
*/
|
||||
NodeGroup getNodes();
|
||||
|
||||
/**
|
||||
* Gets a property from the config.
|
||||
*
|
||||
* @param name The name of the property.
|
||||
* @return A {@link Try} with the value of the property, otherwise a {@link Try.Failure} if there is no property by
|
||||
* that name.
|
||||
*/
|
||||
Try<Object> getProperty(String name);
|
||||
|
||||
/**
|
||||
* Sets a property in the config.
|
||||
*
|
||||
* @param name The name of the property.
|
||||
* @param value The value of the property.
|
||||
* @return An empty {@link Try} if the property was set successfully, otherwise a {@link Try.Failure} with the
|
||||
* exception explaining why the property could not be set.
|
||||
*/
|
||||
Try<Void> setProperty(String name, Object value);
|
||||
|
||||
/**
|
||||
* Sets world access permissions should be enforced.
|
||||
* @param enforceAccess The new value.
|
||||
*/
|
||||
void setEnforceAccess(boolean enforceAccess);
|
||||
|
||||
/**
|
||||
* Gets enforceAccess.
|
||||
* @return enforceAccess.
|
||||
*/
|
||||
boolean getEnforceAccess();
|
||||
|
||||
/**
|
||||
* Sets whether the game mode should be enforced.
|
||||
* @param enforceGameMode The new value.
|
||||
*/
|
||||
void setEnforceGameMode(boolean enforceGameMode);
|
||||
|
||||
/**
|
||||
* Gets enforceGameMode value.
|
||||
* @return True if game mode should be enforced.
|
||||
*/
|
||||
boolean getEnforceGameMode();
|
||||
|
||||
/**
|
||||
* Sets whether or not the automatic purge of entities is enabled.
|
||||
*
|
||||
* @param autopurge True if automatic purge should be enabled.
|
||||
*/
|
||||
void setAutoPurgeEntities(boolean autopurge);
|
||||
|
||||
/**
|
||||
* Gets whether or not the automatic purge of entities is enabled.
|
||||
*
|
||||
* @return True if automatic purge is enabled.
|
||||
*/
|
||||
boolean isAutoPurgeEntities();
|
||||
|
||||
/**
|
||||
* Sets teleportIntercept.
|
||||
* @param teleportIntercept The new value.
|
||||
*/
|
||||
void setTeleportIntercept(boolean teleportIntercept);
|
||||
|
||||
/**
|
||||
* Gets teleportIntercept.
|
||||
* @return teleportIntercept.
|
||||
*/
|
||||
boolean getTeleportIntercept();
|
||||
|
||||
/**
|
||||
* Sets firstSpawnOverride.
|
||||
* @param firstSpawnOverride The new value.
|
||||
*/
|
||||
void setFirstSpawnOverride(boolean firstSpawnOverride);
|
||||
|
||||
/**
|
||||
* Gets firstSpawnOverride.
|
||||
* @return firstSpawnOverride.
|
||||
*/
|
||||
boolean getFirstSpawnOverride();
|
||||
|
||||
/**
|
||||
* Sets firstSpawnWorld.
|
||||
* @param firstSpawnWorld The new value.
|
||||
*/
|
||||
void setFirstSpawnLocation(String firstSpawnWorld);
|
||||
|
||||
/**
|
||||
* Gets firstSpawnWorld.
|
||||
* @return firstSpawnWorld.
|
||||
*/
|
||||
String getFirstSpawnLocation();
|
||||
|
||||
/**
|
||||
* Sets whether join destination should be enabled.
|
||||
* @param enableJoinDestination The new value
|
||||
*/
|
||||
void setEnableJoinDestination(boolean enableJoinDestination);
|
||||
|
||||
/**
|
||||
* Gets enableJoinDestination.
|
||||
* @return enableJoinDestination
|
||||
*/
|
||||
boolean getEnableJoinDestination();
|
||||
|
||||
/**
|
||||
* Sets alwaysSpawnDestination.
|
||||
* @param alwaysSpawnDestination The new value
|
||||
*/
|
||||
void setJoinDestination(String alwaysSpawnDestination);
|
||||
|
||||
/**
|
||||
* Gets alwaysSpawnDestination.
|
||||
* @return alwaysSpawnLocation
|
||||
*/
|
||||
String getJoinDestination();
|
||||
|
||||
/**
|
||||
* Sets whether or not to let Bukkit determine portal search radius on its own or if Multiverse should give input.
|
||||
*
|
||||
* @param useDefaultPortalSearch True to let Bukkit determine portal search radius on its own.
|
||||
*/
|
||||
void setUseCustomPortalSearch(boolean useDefaultPortalSearch);
|
||||
|
||||
/**
|
||||
* Gets whether or not Bukkit will be determining portal search radius on its own or if Multiverse should help.
|
||||
*
|
||||
* @return True means Bukkit will use its own default values.
|
||||
*/
|
||||
boolean isUsingCustomPortalSearch();
|
||||
|
||||
/**
|
||||
* Sets the radius at which vanilla style portals will be searched for to connect to worlds together.
|
||||
*
|
||||
* @param searchRadius The portal search radius.
|
||||
*/
|
||||
void setCustomPortalSearchRadius(int searchRadius);
|
||||
|
||||
/**
|
||||
* Gets the radius at which vanilla style portals will be searched for to connect to worlds together.
|
||||
*
|
||||
* @return The portal search radius.
|
||||
*/
|
||||
int getCustomPortalSearchRadius();
|
||||
|
||||
/**
|
||||
* Sets prefixChat.
|
||||
* @param prefixChat The new value.
|
||||
*/
|
||||
void setEnablePrefixChat(boolean prefixChat);
|
||||
|
||||
/**
|
||||
* Gets prefixChat.
|
||||
* @return prefixChat.
|
||||
*/
|
||||
boolean isEnablePrefixChat();
|
||||
|
||||
/**
|
||||
* Sets prefixChatFormat.
|
||||
* @param prefixChatFormat The new value.
|
||||
*/
|
||||
void setPrefixChatFormat(String prefixChatFormat);
|
||||
|
||||
/**
|
||||
* Gets prefixChatFormat.
|
||||
* @return prefixChatFormat.
|
||||
*/
|
||||
String getPrefixChatFormat();
|
||||
|
||||
/**
|
||||
* Sets whether to register the {@link MultiverseCorePlaceholders} class with PlaceholderAPI plugin.
|
||||
* @param registerPapiHook The new value.
|
||||
*/
|
||||
void setRegisterPapiHook(boolean registerPapiHook);
|
||||
|
||||
/**
|
||||
* Gets whether to register the {@link MultiverseCorePlaceholders} class with PlaceholderAPI plugin.
|
||||
* @return registerPapiHook.
|
||||
*/
|
||||
boolean isRegisterPapiHook();
|
||||
|
||||
/**
|
||||
* Sets globalDebug.
|
||||
* @param globalDebug The new value.
|
||||
*/
|
||||
void setGlobalDebug(int globalDebug);
|
||||
|
||||
/**
|
||||
* Gets globalDebug.
|
||||
* @return globalDebug.
|
||||
*/
|
||||
int getGlobalDebug();
|
||||
|
||||
/**
|
||||
* Sets whether to suppress startup messages.
|
||||
*
|
||||
* @param silentStart true to suppress messages.
|
||||
*/
|
||||
void setSilentStart(boolean silentStart);
|
||||
|
||||
/**
|
||||
* Whether we are suppressing startup messages.
|
||||
*
|
||||
* @return true if we are suppressing startup messages.
|
||||
*/
|
||||
boolean getSilentStart();
|
||||
|
||||
/**
|
||||
* Sets whether or not the donation/patreon messages are shown.
|
||||
*
|
||||
* @param idonotwanttodonate True if donation/patreon messages should be shown.
|
||||
*/
|
||||
void setShowDonateMessage(boolean idonotwanttodonate);
|
||||
|
||||
/**
|
||||
* Gets whether or not the donation/patreon messages are shown.
|
||||
*
|
||||
* @return True if donation/patreon messages should be shown.
|
||||
*/
|
||||
boolean isShowingDonateMessage();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/******************************************************************************
|
||||
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
|
||||
* Multiverse 2 is licensed under the BSD License. *
|
||||
* For more information please check the README.md file included *
|
||||
* with this project. *
|
||||
******************************************************************************/
|
||||
|
||||
package org.mvplugins.multiverse.core.api;
|
||||
|
||||
/**
|
||||
* Multiverse 2 Core API
|
||||
* <p>
|
||||
* This API contains a bunch of useful things you can get out of Multiverse in general!
|
||||
*/
|
||||
public interface MVCore extends MVPlugin {
|
||||
|
||||
/**
|
||||
* Saves all configs.
|
||||
*
|
||||
* @return Whether the config was successfully saved
|
||||
*/
|
||||
boolean saveAllConfigs();
|
||||
|
||||
/**
|
||||
* Decrements the number of plugins that have specifically hooked into core.
|
||||
*/
|
||||
void decrementPluginCount();
|
||||
|
||||
/**
|
||||
* Increments the number of plugins that have specifically hooked into core.
|
||||
*/
|
||||
void incrementPluginCount();
|
||||
|
||||
/**
|
||||
* Returns the number of plugins that have specifically hooked into core.
|
||||
*
|
||||
* @return The number if plugins that have hooked into core.
|
||||
*/
|
||||
int getPluginCount();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/******************************************************************************
|
||||
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
|
||||
* Multiverse 2 is licensed under the BSD License. *
|
||||
* For more information please check the README.md file included *
|
||||
* with this project. *
|
||||
******************************************************************************/
|
||||
|
||||
package org.mvplugins.multiverse.core.api;
|
||||
|
||||
/**
|
||||
* This interface is implemented by every official Multiverse-plugin.
|
||||
*/
|
||||
public interface MVPlugin {
|
||||
/**
|
||||
* Gets the reference to MultiverseCore.
|
||||
*
|
||||
* @return A valid {@link org.mvplugins.multiverse.core.MultiverseCore}.
|
||||
*/
|
||||
MVCore getCore();
|
||||
|
||||
/**
|
||||
* Allows Multiverse or a plugin to query another Multiverse plugin to see what version its protocol is. This
|
||||
* number
|
||||
* should change when something will break the code.
|
||||
*
|
||||
* @return The Integer protocol version.
|
||||
*/
|
||||
int getProtocolVersion();
|
||||
|
||||
/**
|
||||
* Parse the Authors Array into a readable String with ',' and 'and'.
|
||||
*
|
||||
* @return The readable authors-{@link String}
|
||||
*/
|
||||
String getAuthors();
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package org.mvplugins.multiverse.core.api;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jvnet.hk2.annotations.Contract;
|
||||
|
||||
import org.mvplugins.multiverse.core.destination.ParsedDestination;
|
||||
import org.mvplugins.multiverse.core.teleportation.TeleportResult;
|
||||
|
||||
/**
|
||||
* Used to safely teleport people.
|
||||
*/
|
||||
@Contract
|
||||
public interface SafeTTeleporter extends Teleporter {
|
||||
|
||||
/**
|
||||
* Gets the next safe location around the given location.
|
||||
* @param l A {@link Location}.
|
||||
* @return A safe {@link Location}.
|
||||
*/
|
||||
Location getSafeLocation(Location l);
|
||||
|
||||
/**
|
||||
* Gets the next safe location around the given location.
|
||||
* @param l A {@link Location}.
|
||||
* @param tolerance The tolerance.
|
||||
* @param radius The radius.
|
||||
* @return A safe {@link Location}.
|
||||
*/
|
||||
Location getSafeLocation(Location l, int tolerance, int radius);
|
||||
|
||||
/**
|
||||
* Safely teleport the entity to the MVDestination. This will perform checks to see if the place is safe, and if
|
||||
* it's not, will adjust the final destination accordingly.
|
||||
*
|
||||
* @param teleporter Person who performed the teleport command.
|
||||
* @param teleportee Entity to teleport
|
||||
* @param destination Destination to teleport them to
|
||||
* @return true for success, false for failure
|
||||
*/
|
||||
@Deprecated
|
||||
TeleportResult safelyTeleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination);
|
||||
|
||||
/**
|
||||
* Safely teleport the entity to the MVDestination. This will perform checks to see if the place is safe, and if
|
||||
* it's not, will adjust the final destination accordingly.
|
||||
*
|
||||
* @param teleporter Person who performed the teleport command.
|
||||
* @param teleportee Entity to teleport
|
||||
* @param destination Destination to teleport them to
|
||||
* @return true for success, false for failure
|
||||
*/
|
||||
CompletableFuture<TeleportResult> safelyTeleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination);
|
||||
|
||||
/**
|
||||
* Safely teleport the entity to the Location. This may perform checks to
|
||||
* see if the place is safe, and if
|
||||
* it's not, will adjust the final destination accordingly.
|
||||
*
|
||||
* @param teleporter Person who issued the teleport command.
|
||||
* @param teleportee Entity to teleport.
|
||||
* @param location Location to teleport them to.
|
||||
* @param safely Should the destination be checked for safety before teleport?
|
||||
* @return true for success, false for failure.
|
||||
*/
|
||||
TeleportResult safelyTeleport(CommandSender teleporter, Entity teleportee, Location location,
|
||||
boolean safely);
|
||||
|
||||
/**
|
||||
* Returns a safe location for the entity to spawn at.
|
||||
*
|
||||
* @param entity The entity to spawn
|
||||
* @param destination The MVDestination to take the entity to.
|
||||
* @return A new location to spawn the entity at.
|
||||
*/
|
||||
Location getSafeLocation(Entity entity, DestinationInstance destination);
|
||||
|
||||
/**
|
||||
* Finds a portal-block next to the specified {@link Location}.
|
||||
* @param l The {@link Location}
|
||||
* @return The next portal-block's {@link Location}.
|
||||
*/
|
||||
Location findPortalBlockNextTo(Location l);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.mvplugins.multiverse.core.api;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jvnet.hk2.annotations.Contract;
|
||||
|
||||
import org.mvplugins.multiverse.core.destination.ParsedDestination;
|
||||
import org.mvplugins.multiverse.core.teleportation.TeleportResult;
|
||||
|
||||
@Contract
|
||||
public interface Teleporter {
|
||||
/**
|
||||
* Teleport the entity to the Multiverse Destination.
|
||||
*
|
||||
* @param teleporter Person who performed the teleport command.
|
||||
* @param teleportee Entity to teleport
|
||||
* @param destination Destination to teleport them to
|
||||
* @return true for success, false for failure
|
||||
*/
|
||||
@Deprecated
|
||||
TeleportResult teleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination);
|
||||
|
||||
/**
|
||||
* Teleport the entity to the Multiverse Destination.
|
||||
*
|
||||
* @param teleporter Person who performed the teleport command.
|
||||
* @param teleportee Entity to teleport
|
||||
* @param destination Destination to teleport them to
|
||||
* @return true for success, false for failure
|
||||
*/
|
||||
CompletableFuture<TeleportResult> teleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* The Multiverse-API, containing lots of interfaces that can be quite useful for other
|
||||
* plugins when interacting with Multiverse.
|
||||
*/
|
||||
package org.mvplugins.multiverse.core.api;
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command;
|
||||
|
||||
/**
|
||||
* Extends a command class to add legacy alias annotations.
|
||||
*/
|
||||
public interface LegacyAliasCommand {
|
||||
}
|
||||
@@ -1,364 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import co.aikar.commands.BukkitCommandCompletionContext;
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
import co.aikar.commands.PaperCommandCompletions;
|
||||
import co.aikar.commands.RegisteredCommand;
|
||||
import co.aikar.commands.RootCommand;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import io.vavr.control.Option;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Difficulty;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.SpawnCategory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.anchor.AnchorManager;
|
||||
import org.mvplugins.multiverse.core.anchor.MultiverseAnchor;
|
||||
import org.mvplugins.multiverse.core.command.context.issueraware.IssuerAwareValue;
|
||||
import org.mvplugins.multiverse.core.command.context.issueraware.MultiverseWorldValue;
|
||||
import org.mvplugins.multiverse.core.command.context.issueraware.PlayerArrayValue;
|
||||
import org.mvplugins.multiverse.core.config.CoreConfig;
|
||||
import org.mvplugins.multiverse.core.config.node.functions.DefaultSuggesterProvider;
|
||||
import org.mvplugins.multiverse.core.config.handle.PropertyModifyAction;
|
||||
import org.mvplugins.multiverse.core.destination.DestinationInstance;
|
||||
import org.mvplugins.multiverse.core.destination.DestinationSuggestionPacket;
|
||||
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
|
||||
import org.mvplugins.multiverse.core.destination.core.WorldDestination;
|
||||
import org.mvplugins.multiverse.core.permissions.CorePermissionsChecker;
|
||||
import org.mvplugins.multiverse.core.utils.REPatterns;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.generators.GeneratorPlugin;
|
||||
import org.mvplugins.multiverse.core.world.generators.GeneratorProvider;
|
||||
|
||||
import static org.mvplugins.multiverse.core.utils.StringFormatter.addonToCommaSeperated;
|
||||
|
||||
@Service
|
||||
public class MVCommandCompletions extends PaperCommandCompletions {
|
||||
|
||||
private final MVCommandManager commandManager;
|
||||
private final WorldManager worldManager;
|
||||
private final DestinationsProvider destinationsProvider;
|
||||
private final CoreConfig config;
|
||||
private final CorePermissionsChecker corePermissionsChecker;
|
||||
private final AnchorManager anchorManager;
|
||||
private final GeneratorProvider generatorProvider;
|
||||
|
||||
@Inject
|
||||
MVCommandCompletions(
|
||||
@NotNull MVCommandManager mvCommandManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull DestinationsProvider destinationsProvider,
|
||||
@NotNull CoreConfig config,
|
||||
@NotNull CorePermissionsChecker corePermissionsChecker,
|
||||
@NotNull AnchorManager anchorManager,
|
||||
@NotNull GeneratorProvider generatorProvider
|
||||
) {
|
||||
super(mvCommandManager);
|
||||
this.commandManager = mvCommandManager;
|
||||
this.worldManager = worldManager;
|
||||
this.destinationsProvider = destinationsProvider;
|
||||
this.config = config;
|
||||
this.corePermissionsChecker = corePermissionsChecker;
|
||||
this.anchorManager = anchorManager;
|
||||
this.generatorProvider = generatorProvider;
|
||||
|
||||
registerAsyncCompletion("anchornames", this::suggestAnchorNames);
|
||||
registerAsyncCompletion("commands", this::suggestCommands);
|
||||
registerAsyncCompletion("destinations", this::suggestDestinations);
|
||||
registerStaticCompletion("difficulties", suggestEnums(Difficulty.class));
|
||||
registerStaticCompletion("environments", List.of("normal", "nether", "the_end")); // Don't tab complete the "custom" environment
|
||||
registerAsyncCompletion("flags", this::suggestFlags);
|
||||
registerStaticCompletion("gamemodes", suggestEnums(GameMode.class));
|
||||
registerStaticCompletion("gamerules", this::suggestGamerules);
|
||||
registerAsyncCompletion("gamerulesvalues", this::suggestGamerulesValues);
|
||||
registerAsyncCompletion("generatorplugins", this::suggestGeneratorPlugins);
|
||||
registerStaticCompletion("materials", suggestEnums(Material.class));
|
||||
registerStaticCompletion("mvconfigs", config.getStringPropertyHandle().getAllPropertyNames());
|
||||
registerAsyncCompletion("mvconfigvalues", this::suggestMVConfigValues);
|
||||
registerAsyncCompletion("mvworlds", this::suggestMVWorlds);
|
||||
registerAsyncCompletion("mvworldpropsname", this::suggestMVWorldPropsName);
|
||||
registerAsyncCompletion("mvworldpropsvalue", this::suggestMVWorldPropsValue);
|
||||
registerCompletion("playersarray", this::suggestPlayersArray); // getting online players cannot be async
|
||||
registerStaticCompletion("propsmodifyaction", suggestEnums(PropertyModifyAction.class));
|
||||
registerStaticCompletion("spawncategories", suggestEnums(SpawnCategory.class));
|
||||
registerAsyncCompletion("spawncategorypropsname", this::suggestSpawnCategoryPropsName);
|
||||
registerAsyncCompletion("spawncategorypropsvalue", this::suggestSpawnCategoryPropsValue);
|
||||
|
||||
setDefaultCompletion("destinations", DestinationInstance.class);
|
||||
setDefaultCompletion("difficulties", Difficulty.class);
|
||||
setDefaultCompletion("environments", World.Environment.class);
|
||||
setDefaultCompletion("flags", String[].class);
|
||||
setDefaultCompletion("gamemodes", GameMode.class);
|
||||
setDefaultCompletion("gamerules", GameRule.class);
|
||||
setDefaultCompletion("mvworlds", LoadedMultiverseWorld.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler<BukkitCommandCompletionContext> handler) {
|
||||
return super.registerCompletion(id, context ->
|
||||
completeWithPreconditions(context, handler));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler<BukkitCommandCompletionContext> handler) {
|
||||
return super.registerAsyncCompletion(id, context ->
|
||||
completeWithPreconditions(context, handler));
|
||||
}
|
||||
|
||||
private Collection<String> completeWithPreconditions(
|
||||
BukkitCommandCompletionContext context,
|
||||
CommandCompletionHandler<BukkitCommandCompletionContext> handler) {
|
||||
if (context.hasConfig("playerOnly") && !context.getIssuer().isPlayer()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (context.hasConfig("byIssuerForArg")) {
|
||||
Boolean byIssuerForArg = Try.of(() -> context.getContextValueByName(IssuerAwareValue.class, context.getConfig("byIssuerForArg")))
|
||||
.map(IssuerAwareValue::isByIssuer)
|
||||
.getOrElse(false);
|
||||
if (!byIssuerForArg) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
if (context.hasConfig("notByIssuerForArg")) {
|
||||
Boolean byIssuerForArg = Try.of(() -> context.getContextValueByName(IssuerAwareValue.class, context.getConfig("notByIssuerForArg")))
|
||||
.map(IssuerAwareValue::isByIssuer)
|
||||
.getOrElse(false);
|
||||
if (byIssuerForArg) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
if (context.hasConfig("resolveUntil")) {
|
||||
if (!Try.run(() -> context.getContextValueByName(Object.class, context.getConfig("resolveUntil"))).isSuccess()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
if (context.hasConfig("checkPermissions")) {
|
||||
for (String permission : REPatterns.SEMICOLON.split(context.getConfig("checkPermissions"))) {
|
||||
if (!commandManager.getCommandPermissions().hasPermission(context.getIssuer(), permission)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (context.hasConfig("multiple")) {
|
||||
return addonToCommaSeperated(context.getInput(), handler.getCompletions(context));
|
||||
}
|
||||
return handler.getCompletions(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut to suggest enums values
|
||||
*
|
||||
* @param enumClass The enum class with values
|
||||
* @return A collection of possible string values
|
||||
* @param <T> The enum type
|
||||
*/
|
||||
public <T extends Enum<T>> Collection<String> suggestEnums(Class<T> enumClass) {
|
||||
return EnumSet.allOf(enumClass).stream()
|
||||
.map(Enum::name)
|
||||
.map(name -> name.toLowerCase(Locale.ENGLISH))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private Collection<String> suggestAnchorNames(BukkitCommandCompletionContext context) {
|
||||
return anchorManager.getAnchors(context.getPlayer()).stream()
|
||||
.map(MultiverseAnchor::getName)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private Collection<String> suggestCommands(BukkitCommandCompletionContext context) {
|
||||
String rootCmdName = context.getConfig();
|
||||
if (rootCmdName == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
RootCommand rootCommand = this.commandManager.getRegisteredRootCommands().stream()
|
||||
.unordered()
|
||||
.filter(c -> c.getCommandName().equals(rootCmdName))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (rootCommand == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return rootCommand.getSubCommands().entries().stream()
|
||||
.filter(entry -> checkPerms(context.getIssuer(), entry.getValue()))
|
||||
.map(Map.Entry::getKey)
|
||||
.filter(cmdName -> !cmdName.startsWith("__"))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean checkPerms(CommandIssuer issuer, RegisteredCommand<?> command) {
|
||||
return this.commandManager.hasPermission(issuer, command.getRequiredPermissions());
|
||||
}
|
||||
|
||||
private Collection<String> suggestDestinations(BukkitCommandCompletionContext context) {
|
||||
return Try.of(() -> context.getContextValue(PlayerArrayValue.class))
|
||||
.map(PlayerArrayValue::value)
|
||||
.recover(IllegalStateException.class, e -> context.getContextValue(Player[].class))
|
||||
.recover(IllegalStateException.class, e -> new Player[]{context.getContextValue(Player.class)})
|
||||
.map(players -> {
|
||||
if (players.length == 0) {
|
||||
// Most likely console did not specify a player
|
||||
return Collections.<String>emptyList();
|
||||
}
|
||||
CommandSender sender = context.getIssuer().getIssuer();
|
||||
if (context.hasConfig("othersOnly") && (players.length == 1 && players[0].equals(sender))) {
|
||||
return Collections.<String>emptyList();
|
||||
}
|
||||
return suggestDestinationsWithPerms(sender, Arrays.asList(players), context.getInput());
|
||||
})
|
||||
.getOrElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
private Collection<String> suggestDestinationsWithPerms(CommandSender teleporter, List<Entity> teleportees, String deststring) {
|
||||
return destinationsProvider.suggestDestinations(teleporter, deststring).stream()
|
||||
.filter(packet -> !config.getSimplifiedDestinationTabCompletion()
|
||||
|| packet.destination() instanceof WorldDestination
|
||||
|| deststring.startsWith(packet.destination().getIdentifier() + ":"))
|
||||
.filter(packet -> corePermissionsChecker
|
||||
.checkDestinationPacketPermission(teleporter, teleportees, packet))
|
||||
.map(DestinationSuggestionPacket::parsableString)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private Collection<String> suggestFlags(@NotNull BukkitCommandCompletionContext context) {
|
||||
String groupName = context.getConfig("groupName", "");
|
||||
|
||||
return Try.of(() -> context.getContextValue(String[].class))
|
||||
.map(flags -> commandManager.getFlagsManager().suggest(groupName, flags))
|
||||
.getOrElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
private Collection<String> suggestGamerules() {
|
||||
return Arrays.stream(GameRule.values()).map(GameRule::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Collection<String> suggestGamerulesValues(BukkitCommandCompletionContext context) {
|
||||
return Try.of(() -> context.getContextValue(GameRule.class))
|
||||
// Just use our suggester from configuration lib since gamerules are only boolean or int
|
||||
.mapTry(gamerule -> Option.of(DefaultSuggesterProvider.getDefaultSuggester(gamerule.getType()))
|
||||
.map(s -> s.suggest(context.getInput())).getOrElse(Collections.emptyList()))
|
||||
.getOrElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
private Collection<String> suggestGeneratorPlugins(BukkitCommandCompletionContext context) {
|
||||
return generatorProvider.getRegisteredGeneratorPlugins().stream()
|
||||
.map(GeneratorPlugin::getPluginName)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private Collection<String> suggestMVConfigValues(BukkitCommandCompletionContext context) {
|
||||
return Try.of(() -> context.getContextValue(String.class))
|
||||
.map(propertyName -> config.getStringPropertyHandle()
|
||||
.getSuggestedPropertyValue(propertyName, context.getInput(), PropertyModifyAction.SET, context.getSender()))
|
||||
.getOrElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
private Collection<String> suggestMVWorlds(BukkitCommandCompletionContext context) {
|
||||
String scope = context.getConfig("scope", "loaded");
|
||||
switch (scope) {
|
||||
case "both" -> {
|
||||
return worldManager.getWorlds().stream()
|
||||
.map(MultiverseWorld::getTabCompleteName)
|
||||
.toList();
|
||||
}
|
||||
case "loaded" -> {
|
||||
return worldManager.getLoadedWorlds().stream()
|
||||
.map(MultiverseWorld::getTabCompleteName)
|
||||
.toList();
|
||||
}
|
||||
case "unloaded" -> {
|
||||
return worldManager.getUnloadedWorlds().stream()
|
||||
.map(MultiverseWorld::getTabCompleteName)
|
||||
.toList();
|
||||
}
|
||||
case "potential" -> {
|
||||
return worldManager.getPotentialWorlds();
|
||||
}
|
||||
}
|
||||
Logging.severe("Invalid MVWorld scope: " + scope);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private Collection<String> suggestMVWorldPropsName(BukkitCommandCompletionContext context) {
|
||||
return Try.of(() -> {
|
||||
MultiverseWorld world = context.getContextValue(MultiverseWorldValue.class).value();
|
||||
PropertyModifyAction action = context.getContextValue(PropertyModifyAction.class);
|
||||
return world.getStringPropertyHandle().getModifiablePropertyNames(action);
|
||||
}).getOrElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
private Collection<String> suggestMVWorldPropsValue(BukkitCommandCompletionContext context) {
|
||||
return Try.of(() -> {
|
||||
MultiverseWorld world = context.getContextValue(MultiverseWorldValue.class).value();
|
||||
PropertyModifyAction action = context.getContextValue(PropertyModifyAction.class);
|
||||
String propertyName = context.getContextValue(String.class);
|
||||
return world.getStringPropertyHandle().getSuggestedPropertyValue(propertyName, context.getInput(), action, context.getSender());
|
||||
}).getOrElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
private Collection<String> suggestPlayersArray(BukkitCommandCompletionContext context) {
|
||||
CommandSender sender = context.getSender();
|
||||
Validate.notNull(sender, "Sender cannot be null");
|
||||
Player senderPlayer = sender instanceof Player ? (Player)sender : null;
|
||||
List<String> matchedPlayers = new ArrayList<>();
|
||||
|
||||
for(Player player : Bukkit.getOnlinePlayers()) {
|
||||
String name = player.getName();
|
||||
if ((senderPlayer == null || senderPlayer.canSee(player))
|
||||
&& (!context.hasConfig("excludeSelf") || !player.equals(senderPlayer))) {
|
||||
matchedPlayers.add(name);
|
||||
}
|
||||
}
|
||||
return addonToCommaSeperated(context.getInput(), matchedPlayers);
|
||||
}
|
||||
|
||||
private Collection<String> suggestSpawnCategoryPropsName(BukkitCommandCompletionContext context) {
|
||||
return Try.of(() -> {
|
||||
MultiverseWorld world = context.getContextValue(MultiverseWorld.class);
|
||||
SpawnCategory spawnCategory = context.getContextValue(SpawnCategory.class);
|
||||
PropertyModifyAction action = context.getContextValue(PropertyModifyAction.class);
|
||||
return world.getEntitySpawnConfig()
|
||||
.getSpawnCategoryConfig(spawnCategory)
|
||||
.getStringPropertyHandle()
|
||||
.getModifiablePropertyNames(action);
|
||||
}).getOrElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
private Collection<String> suggestSpawnCategoryPropsValue(BukkitCommandCompletionContext context) {
|
||||
return Try.of(() -> {
|
||||
MultiverseWorld world = context.getContextValue(MultiverseWorld.class);
|
||||
SpawnCategory spawnCategory = context.getContextValue(SpawnCategory.class);
|
||||
PropertyModifyAction action = context.getContextValue(PropertyModifyAction.class);
|
||||
String propertyName = context.getContextValue(String.class);
|
||||
return world.getEntitySpawnConfig()
|
||||
.getSpawnCategoryConfig(spawnCategory)
|
||||
.getStringPropertyHandle()
|
||||
.getSuggestedPropertyValue(propertyName, context.getInput(), action, context.getSender());
|
||||
}).getOrElse(Collections.emptyList());
|
||||
}
|
||||
}
|
||||
@@ -1,396 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import co.aikar.commands.ACFUtil;
|
||||
import co.aikar.commands.BukkitCommandExecutionContext;
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.InvalidCommandArgument;
|
||||
import co.aikar.commands.MinecraftMessageKeys;
|
||||
import co.aikar.commands.PaperCommandContexts;
|
||||
import co.aikar.commands.contexts.ContextResolver;
|
||||
import com.google.common.base.Strings;
|
||||
import io.vavr.control.Option;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.BlockCommandSender;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.SpawnCategory;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.anchor.AnchorManager;
|
||||
import org.mvplugins.multiverse.core.anchor.MultiverseAnchor;
|
||||
import org.mvplugins.multiverse.core.command.context.GameRuleValue;
|
||||
import org.mvplugins.multiverse.core.command.context.issueraware.IssuerAwareContextBuilder;
|
||||
import org.mvplugins.multiverse.core.command.context.PlayerLocation;
|
||||
import org.mvplugins.multiverse.core.command.context.issueraware.MultiverseWorldValue;
|
||||
import org.mvplugins.multiverse.core.command.context.issueraware.PlayerArrayValue;
|
||||
import org.mvplugins.multiverse.core.config.CoreConfig;
|
||||
import org.mvplugins.multiverse.core.destination.DestinationInstance;
|
||||
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
|
||||
import org.mvplugins.multiverse.core.display.filters.ContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.filters.RegexContentFilter;
|
||||
import org.mvplugins.multiverse.core.exceptions.command.MVInvalidCommandArgument;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
import org.mvplugins.multiverse.core.utils.PlayerFinder;
|
||||
import org.mvplugins.multiverse.core.utils.REPatterns;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.generators.GeneratorPlugin;
|
||||
import org.mvplugins.multiverse.core.world.generators.GeneratorProvider;
|
||||
|
||||
@Service
|
||||
public class MVCommandContexts extends PaperCommandContexts {
|
||||
|
||||
private final MVCommandManager mvCommandManager;
|
||||
private final DestinationsProvider destinationsProvider;
|
||||
private final WorldManager worldManager;
|
||||
private final CoreConfig config;
|
||||
private final AnchorManager anchorManager;
|
||||
private final GeneratorProvider generatorProvider;
|
||||
|
||||
@Inject
|
||||
MVCommandContexts(
|
||||
MVCommandManager mvCommandManager,
|
||||
DestinationsProvider destinationsProvider,
|
||||
WorldManager worldManager,
|
||||
CoreConfig config,
|
||||
AnchorManager anchorManager,
|
||||
GeneratorProvider generatorProvider
|
||||
) {
|
||||
super(mvCommandManager);
|
||||
this.mvCommandManager = mvCommandManager;
|
||||
this.destinationsProvider = destinationsProvider;
|
||||
this.worldManager = worldManager;
|
||||
this.config = config;
|
||||
this.anchorManager = anchorManager;
|
||||
this.generatorProvider = generatorProvider;
|
||||
|
||||
registerIssuerOnlyContext(BukkitCommandIssuer.class, BukkitCommandExecutionContext::getIssuer);
|
||||
registerIssuerOnlyContext(MVCommandIssuer.class, this::parseMVCommandIssuer);
|
||||
registerOptionalContext(ContentFilter.class, this::parseContentFilter);
|
||||
registerContext(DestinationInstance.class, this::parseDestination);
|
||||
registerContext(GameRule.class, this::parseGameRule);
|
||||
registerContext(GameRuleValue.class, this::parseGameRuleValue);
|
||||
registerContext(GeneratorPlugin.class, this::parseGeneratorPlugin);
|
||||
registerIssuerAwareContext(LoadedMultiverseWorld.class, loadedMultiverseWorldContextBuilder().generateContext());
|
||||
registerIssuerAwareContext(LoadedMultiverseWorld[].class, loadedMultiverseWorldArrayContextBuilder().generateContext());
|
||||
registerIssuerAwareContext(MultiverseWorld.class, multiverseWorldContextBuilder().generateContext());
|
||||
registerIssuerAwareContext(MultiverseWorldValue.class, multiverseWorldContextBuilder().generateContext(MultiverseWorldValue::new));
|
||||
registerIssuerAwareContext(MultiverseWorld[].class, multiverseWorldArrayContextBuilder().generateContext());
|
||||
registerContext(MultiverseAnchor.class, this::parseMultiverseAnchor);
|
||||
registerIssuerAwareContext(Player.class, playerContextBuilder().generateContext());
|
||||
registerIssuerAwareContext(Player[].class, playerArrayContextBuilder().generateContext());
|
||||
registerIssuerAwareContext(PlayerArrayValue.class, playerArrayContextBuilder().generateContext(PlayerArrayValue::new));
|
||||
registerIssuerAwareContext(PlayerLocation.class, this::parsePlayerLocation);
|
||||
registerContext(SpawnCategory[].class, this::parseSpawnCategories);
|
||||
}
|
||||
|
||||
private MVCommandIssuer parseMVCommandIssuer(BukkitCommandExecutionContext context) {
|
||||
if (context.getIssuer() instanceof MVCommandIssuer) {
|
||||
return (MVCommandIssuer) context.getIssuer();
|
||||
}
|
||||
return mvCommandManager.getCommandIssuer(context.getSender());
|
||||
}
|
||||
|
||||
private ContentFilter parseContentFilter(BukkitCommandExecutionContext context) {
|
||||
if (Strings.isNullOrEmpty(context.getFirstArg())) {
|
||||
return DefaultContentFilter.get();
|
||||
}
|
||||
String filterString = context.popFirstArg();
|
||||
return RegexContentFilter.fromString(filterString);
|
||||
}
|
||||
|
||||
private DestinationInstance<?, ?> parseDestination(BukkitCommandExecutionContext context) {
|
||||
String destination = context.popFirstArg();
|
||||
if (Strings.isNullOrEmpty(destination)) {
|
||||
throw new InvalidCommandArgument("No destination specified.");
|
||||
}
|
||||
|
||||
return destinationsProvider.parseDestination(context.getSender(), destination)
|
||||
.getOrThrow(failure ->
|
||||
new InvalidCommandArgument(failure.getFailureMessage().formatted(context.getIssuer())));
|
||||
}
|
||||
|
||||
private GameRule<?> parseGameRule(BukkitCommandExecutionContext context) {
|
||||
String gameRuleName = context.popFirstArg();
|
||||
if (Strings.isNullOrEmpty(gameRuleName)) {
|
||||
throw new InvalidCommandArgument("No game rule specified.");
|
||||
}
|
||||
|
||||
GameRule<?> gameRule = GameRule.getByName(gameRuleName);
|
||||
if (gameRule == null) {
|
||||
throw new InvalidCommandArgument("The game rule " + gameRuleName + " is not valid.");
|
||||
}
|
||||
|
||||
return gameRule;
|
||||
}
|
||||
|
||||
private GameRuleValue parseGameRuleValue(BukkitCommandExecutionContext context) {
|
||||
GameRule<?> gameRule = (GameRule<?>) context.getResolvedArg(GameRule.class);
|
||||
if (gameRule == null) {
|
||||
throw new InvalidCommandArgument("No game rule specified.");
|
||||
}
|
||||
String valueString = context.getFirstArg();
|
||||
if (Strings.isNullOrEmpty(valueString)) {
|
||||
throw new InvalidCommandArgument("No game rule value specified.");
|
||||
}
|
||||
|
||||
ContextResolver<?, BukkitCommandExecutionContext> resolver = getResolver(gameRule.getType());
|
||||
if (resolver == null) {
|
||||
return new GameRuleValue(valueString);
|
||||
}
|
||||
|
||||
Object resolvedValue = resolver.getContext(context);
|
||||
if (resolvedValue == null) {
|
||||
throw new InvalidCommandArgument("The game rule value " + valueString + " is not valid for game rule " + gameRule.getName() + ".");
|
||||
}
|
||||
|
||||
return new GameRuleValue(resolvedValue);
|
||||
}
|
||||
|
||||
private GeneratorPlugin parseGeneratorPlugin(BukkitCommandExecutionContext context) {
|
||||
GeneratorPlugin generatorPlugin = generatorProvider.getGeneratorPlugin(context.popFirstArg());
|
||||
if (generatorPlugin == null) {
|
||||
throw new InvalidCommandArgument("Invalid generator plugin: " + context.getFirstArg());
|
||||
}
|
||||
return generatorPlugin;
|
||||
}
|
||||
|
||||
|
||||
private IssuerAwareContextBuilder<LoadedMultiverseWorld> loadedMultiverseWorldContextBuilder() {
|
||||
return new IssuerAwareContextBuilder<LoadedMultiverseWorld>()
|
||||
.fromPlayer((context, player) -> worldManager.getLoadedWorld(player.getWorld()).getOrNull())
|
||||
.fromInput((context, input) -> getLoadedMultiverseWorld(input))
|
||||
.issuerOnlyFailMessage((context) -> Message.of("This command can only be used by a player in a loaded Multiverse World."))
|
||||
.issuerAwarePlayerFailMessage((context, player) -> Message.of("You are not in a loaded multiverse world. Either specify a multiverse world name or use this command in a loaded multiverse world."))
|
||||
.issuerAwareInputFailMessage((context, input) -> Message.of("World '" + input + "' is not a loaded multiverse world. Remember to specify the world name when using this command in console."))
|
||||
.inputOnlyFailMessage((context, input) -> Message.of("World " + input + " is not a loaded multiverse world."));
|
||||
}
|
||||
|
||||
private IssuerAwareContextBuilder<LoadedMultiverseWorld[]> loadedMultiverseWorldArrayContextBuilder() {
|
||||
return new IssuerAwareContextBuilder<LoadedMultiverseWorld[]>()
|
||||
.fromPlayer((context, player) -> worldManager.getLoadedWorld(player.getWorld())
|
||||
.map(world -> new LoadedMultiverseWorld[]{world})
|
||||
.getOrNull())
|
||||
.fromInput((context, input) -> {
|
||||
String[] worldNames = input == null ? new String[0] : REPatterns.COMMA.split(input);
|
||||
Set<LoadedMultiverseWorld> worlds = new HashSet<>(worldNames.length);
|
||||
for (String worldName : worldNames) {
|
||||
if ("*".equals(worldName)) {
|
||||
worlds.addAll(worldManager.getLoadedWorlds());
|
||||
break;
|
||||
}
|
||||
LoadedMultiverseWorld world = getLoadedMultiverseWorld(worldName);
|
||||
if (world == null) {
|
||||
throw new InvalidCommandArgument("World " + worldName + " is not a loaded multiverse world.");
|
||||
}
|
||||
worlds.add(world);
|
||||
}
|
||||
return worlds.isEmpty() ? null : worlds.toArray(new LoadedMultiverseWorld[0]);
|
||||
})
|
||||
.issuerOnlyFailMessage((context) -> Message.of("This command can only be used by a player in a loaded Multiverse World."))
|
||||
.issuerAwarePlayerFailMessage((context, player) -> Message.of("You are not in a loaded multiverse world. Either specify a multiverse world name or use this command in a loaded multiverse world."))
|
||||
.issuerAwareInputFailMessage((context, input) -> Message.of("World '" + input + "' is not a loaded multiverse world. Remember to specify the world name when using this command in console."))
|
||||
.inputOnlyFailMessage((context, input) -> Message.of("World " + input + " is not a loaded multiverse world."));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private LoadedMultiverseWorld getLoadedMultiverseWorld(String worldName) {
|
||||
return config.getResolveAliasName()
|
||||
? worldManager.getLoadedWorldByNameOrAlias(worldName).getOrNull()
|
||||
: worldManager.getLoadedWorld(worldName).getOrNull();
|
||||
}
|
||||
|
||||
private IssuerAwareContextBuilder<MultiverseWorld> multiverseWorldContextBuilder() {
|
||||
return new IssuerAwareContextBuilder<MultiverseWorld>()
|
||||
.fromPlayer((context, player) -> worldManager.getWorld(player.getWorld()).getOrNull())
|
||||
.fromInput((context, input) -> getMultiverseWorld(input))
|
||||
.issuerOnlyFailMessage((context) -> Message.of("This command can only be used by a player in a Multiverse World."))
|
||||
.issuerAwarePlayerFailMessage((context, player) -> Message.of("You are not in a multiverse world. Either specify a multiverse world name or use this command in a multiverse world."))
|
||||
.issuerAwareInputFailMessage((context, input) -> Message.of("World '" + input + "' is not a multiverse world. Remember to specify the world name when using this command in console."))
|
||||
.inputOnlyFailMessage((context, input) -> Message.of("World " + input + " is not a multiverse world."));
|
||||
}
|
||||
|
||||
private IssuerAwareContextBuilder<MultiverseWorld[]> multiverseWorldArrayContextBuilder() {
|
||||
return new IssuerAwareContextBuilder<MultiverseWorld[]>()
|
||||
.fromPlayer((context, player) -> worldManager.getWorld(player.getWorld())
|
||||
.map(world -> new MultiverseWorld[]{world})
|
||||
.getOrNull())
|
||||
.fromInput((context, input) -> {
|
||||
String[] worldNames = input == null ? new String[0] : REPatterns.COMMA.split(input);
|
||||
Set<MultiverseWorld> worlds = new HashSet<>(worldNames.length);
|
||||
for (String worldName : worldNames) {
|
||||
if ("*".equals(worldName)) {
|
||||
worlds.addAll(worldManager.getWorlds());
|
||||
break;
|
||||
}
|
||||
MultiverseWorld world = getMultiverseWorld(worldName);
|
||||
if (world == null) {
|
||||
throw new InvalidCommandArgument("World " + worldName + " is not a multiverse world.");
|
||||
}
|
||||
worlds.add(world);
|
||||
}
|
||||
return worlds.isEmpty() ? null : worlds.toArray(new MultiverseWorld[0]);
|
||||
})
|
||||
.issuerOnlyFailMessage((context) -> Message.of("This command can only be used by a player in a Multiverse World."))
|
||||
.issuerAwarePlayerFailMessage((context, player) -> Message.of("You are not in a multiverse world. Either specify a multiverse world name or use this command in a multiverse world."))
|
||||
.issuerAwareInputFailMessage((context, input) -> Message.of("World '" + input + "' is not a multiverse world. Remember to specify the world name when using this command in console."))
|
||||
.inputOnlyFailMessage((context, input) -> Message.of("World " + input + " is not a multiverse world."));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private MultiverseWorld getMultiverseWorld(String worldName) {
|
||||
return config.getResolveAliasName()
|
||||
? worldManager.getWorldByNameOrAlias(worldName).getOrNull()
|
||||
: worldManager.getWorld(worldName).getOrNull();
|
||||
}
|
||||
|
||||
private MultiverseAnchor parseMultiverseAnchor(BukkitCommandExecutionContext context) {
|
||||
String anchorName = context.popFirstArg();
|
||||
return anchorManager.getAnchor(anchorName)
|
||||
.getOrElseThrow(() -> new InvalidCommandArgument("The anchor '" +anchorName + "' does not exist."));
|
||||
}
|
||||
|
||||
private IssuerAwareContextBuilder<Player> playerContextBuilder() {
|
||||
return new IssuerAwareContextBuilder<Player>()
|
||||
.fromPlayer((context, player) -> player)
|
||||
.fromInput((context, input) -> PlayerFinder.get(input, context.getSender()))
|
||||
.issuerOnlyFailMessage((context) -> Message.of("This command can only be used by a player."))
|
||||
.issuerAwareInputFailMessage((context, input) -> Message.of("Invalid player: " + input + ". Either specify an online player or use this command as a player."))
|
||||
.inputOnlyFailMessage((context, input) -> Message.of("Player " + input + " not found."));
|
||||
}
|
||||
|
||||
private IssuerAwareContextBuilder<Player[]> playerArrayContextBuilder() {
|
||||
return new IssuerAwareContextBuilder<Player[]>()
|
||||
.fromPlayer((context, player) -> new Player[]{player})
|
||||
.fromInput((context, input) -> PlayerFinder
|
||||
.tryGetMulti(input, context.getSender())
|
||||
.map(list -> list.toArray(new Player[0]))
|
||||
.map(arr -> (arr.length == 0) ? null : arr)
|
||||
.getOrElseThrow(failure -> {
|
||||
if (failure instanceof MVInvalidCommandArgument mvFailure) {
|
||||
throw mvFailure;
|
||||
}
|
||||
throw new InvalidCommandArgument(failure.getLocalizedMessage() + " "
|
||||
+ Option.of(failure.getCause()).map(Throwable::getLocalizedMessage).getOrElse(""));
|
||||
}))
|
||||
.issuerOnlyFailMessage((context) -> Message.of("This command can only be used by a player."))
|
||||
.issuerAwareInputFailMessage((context, input) -> Message.of("Invalid player: " + input + ". Either specify an online player or use this command as a player."))
|
||||
.inputOnlyFailMessage((context, input) -> {
|
||||
if (PlayerFinder.isSelector(input)) {
|
||||
return Message.of("No player(s) matched selector: " + input + ".");
|
||||
}
|
||||
return Message.of("Player(s) " + input + " not found.");
|
||||
});
|
||||
}
|
||||
|
||||
private PlayerLocation parsePlayerLocation(BukkitCommandExecutionContext context) {
|
||||
Try<Location> location = Try.of(() -> parseLocationFromInput(context.getFirstArg(), context.getSender()));
|
||||
|
||||
if (location.isSuccess()) {
|
||||
context.popFirstArg();
|
||||
return new PlayerLocation(location.get());
|
||||
}
|
||||
if (context.getPlayer() != null) {
|
||||
return new PlayerLocation(context.getPlayer().getLocation());
|
||||
}
|
||||
if (context.getFirstArg() == null) {
|
||||
throw new InvalidCommandArgument("You must specify a world location when using this command in console.");
|
||||
}
|
||||
if (location.getCause() instanceof InvalidCommandArgument) {
|
||||
throw (InvalidCommandArgument)location.getCause();
|
||||
}
|
||||
throw new RuntimeException(location.getCause());
|
||||
}
|
||||
|
||||
// copied from ACF
|
||||
private Location parseLocationFromInput(String input, CommandSender sender) {
|
||||
String[] split = REPatterns.COLON.split(input, 2);
|
||||
if (split.length == 0) {
|
||||
throw new InvalidCommandArgument(true);
|
||||
} else if (split.length < 2 && !(sender instanceof Player) && !(sender instanceof BlockCommandSender)) {
|
||||
throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_WORLD, new String[0]);
|
||||
} else {
|
||||
Location sourceLoc = null;
|
||||
String world;
|
||||
String rest;
|
||||
if (split.length == 2) {
|
||||
world = split[0];
|
||||
rest = split[1];
|
||||
} else if (sender instanceof Player) {
|
||||
sourceLoc = ((Player)sender).getLocation();
|
||||
world = sourceLoc.getWorld().getName();
|
||||
rest = split[0];
|
||||
} else {
|
||||
if (!(sender instanceof BlockCommandSender)) {
|
||||
throw new InvalidCommandArgument(true);
|
||||
}
|
||||
|
||||
sourceLoc = ((BlockCommandSender)sender).getBlock().getLocation();
|
||||
world = sourceLoc.getWorld().getName();
|
||||
rest = split[0];
|
||||
}
|
||||
|
||||
boolean rel = rest.startsWith("~");
|
||||
split = REPatterns.COMMA.split(rel ? rest.substring(1) : rest);
|
||||
if (split.length < 3) {
|
||||
throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_XYZ, new String[0]);
|
||||
} else {
|
||||
Double x = ACFUtil.parseDouble(split[0], rel ? (double)0.0F : null);
|
||||
Double y = ACFUtil.parseDouble(split[1], rel ? (double)0.0F : null);
|
||||
Double z = ACFUtil.parseDouble(split[2], rel ? (double)0.0F : null);
|
||||
if (sourceLoc != null && rel) {
|
||||
x = x + sourceLoc.getX();
|
||||
y = y + sourceLoc.getY();
|
||||
z = z + sourceLoc.getZ();
|
||||
} else if (rel) {
|
||||
throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_CONSOLE_NOT_RELATIVE, new String[0]);
|
||||
}
|
||||
|
||||
if (x != null && y != null && z != null) {
|
||||
World worldObj = Bukkit.getWorld(world);
|
||||
if (worldObj == null) {
|
||||
throw new InvalidCommandArgument(MinecraftMessageKeys.INVALID_WORLD, new String[0]);
|
||||
} else if (split.length >= 5) {
|
||||
Float yaw = ACFUtil.parseFloat(split[3]);
|
||||
Float pitch = ACFUtil.parseFloat(split[4]);
|
||||
if (pitch != null && yaw != null) {
|
||||
return new Location(worldObj, x, y, z, yaw, pitch);
|
||||
} else {
|
||||
throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_XYZ, new String[0]);
|
||||
}
|
||||
} else {
|
||||
return new Location(worldObj, x, y, z);
|
||||
}
|
||||
} else {
|
||||
throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_XYZ, new String[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SpawnCategory[] parseSpawnCategories(BukkitCommandExecutionContext context) {
|
||||
if (context.isOptional() && context.getArgs().isEmpty()) {
|
||||
return new SpawnCategory[0];
|
||||
}
|
||||
Set<SpawnCategory> categories = new HashSet<>();
|
||||
String[] split = REPatterns.COMMA.split(context.popFirstArg());
|
||||
for (String category : split) {
|
||||
SpawnCategory spawnCategory = ACFUtil.simpleMatch(SpawnCategory.class, category);
|
||||
if (spawnCategory != null) {
|
||||
categories.add(spawnCategory);
|
||||
}
|
||||
}
|
||||
return categories.toArray(new SpawnCategory[0]);
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.MessageType;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement;
|
||||
import org.mvplugins.multiverse.core.utils.text.ChatTextFormatter;
|
||||
|
||||
public class MVCommandIssuer extends BukkitCommandIssuer {
|
||||
|
||||
private final MVCommandManager commandManager;
|
||||
|
||||
MVCommandIssuer(@NotNull MVCommandManager commandManager, @NotNull CommandSender sender) {
|
||||
super(commandManager, sender);
|
||||
this.commandManager = commandManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MVCommandManager getManager() {
|
||||
return commandManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessageInternal(String message) {
|
||||
ChatTextFormatter.sendFormattedMessage(getIssuer(), message);
|
||||
}
|
||||
|
||||
public void sendError(String message, MessageReplacement... replacements) {
|
||||
sendMessage(MessageType.ERROR, message, replacements);
|
||||
}
|
||||
|
||||
public void sendSyntax(String message, MessageReplacement... replacements) {
|
||||
sendMessage(MessageType.SYNTAX, message, replacements);
|
||||
}
|
||||
|
||||
public void sendInfo(String message, MessageReplacement... replacements) {
|
||||
sendMessage(MessageType.INFO, message, replacements);
|
||||
}
|
||||
|
||||
public void sendMessage(String message, MessageReplacement... replacements) {
|
||||
sendMessage(null, Message.of(message, replacements));
|
||||
}
|
||||
|
||||
public void sendMessage(MessageType type, String message, MessageReplacement... replacements) {
|
||||
sendMessage(type, Message.of(message, replacements));
|
||||
}
|
||||
|
||||
public void sendMessage(MessageType messageType, String message) {
|
||||
var formatter = getManager().getFormat(messageType);
|
||||
if (formatter != null) {
|
||||
sendMessage(formatter.format(message));
|
||||
} else {
|
||||
sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendError(MessageKeyProvider key) {
|
||||
sendMessage(MessageType.ERROR, key, new String[0]);
|
||||
}
|
||||
|
||||
public void sendSyntax(MessageKeyProvider key) {
|
||||
sendMessage(MessageType.SYNTAX, key, new String[0]);
|
||||
}
|
||||
|
||||
public void sendInfo(MessageKeyProvider key) {
|
||||
sendMessage(MessageType.INFO, key, new String[0]);
|
||||
}
|
||||
|
||||
public void sendError(MessageKeyProvider key, MessageReplacement... replacements) {
|
||||
sendMessage(MessageType.ERROR, key, replacements);
|
||||
}
|
||||
|
||||
public void sendSyntax(MessageKeyProvider key, MessageReplacement... replacements) {
|
||||
sendMessage(MessageType.SYNTAX, key, replacements);
|
||||
}
|
||||
|
||||
public void sendInfo(MessageKeyProvider key, MessageReplacement... replacements) {
|
||||
sendMessage(MessageType.INFO, key, replacements);
|
||||
}
|
||||
public void sendMessage(MessageKeyProvider key, MessageReplacement... replacements) {
|
||||
sendMessage(null, Message.of(key, replacements));
|
||||
}
|
||||
|
||||
public void sendMessage(MessageType messageType, MessageKeyProvider key, MessageReplacement... replacements) {
|
||||
sendMessage(messageType, Message.of(key, replacements));
|
||||
}
|
||||
|
||||
public void sendError(Message message) {
|
||||
sendMessage(MessageType.ERROR, message);
|
||||
}
|
||||
|
||||
public void sendSyntax(Message message) {
|
||||
sendMessage(MessageType.SYNTAX, message);
|
||||
}
|
||||
|
||||
public void sendInfo(Message message) {
|
||||
sendMessage(MessageType.INFO, message);
|
||||
}
|
||||
|
||||
public void sendMessage(Message message) {
|
||||
sendMessage(null, message);
|
||||
}
|
||||
|
||||
public void sendMessage(MessageType messageType, Message message) {
|
||||
if (message instanceof MessageKeyProvider) {
|
||||
sendMessage(messageType, (MessageKeyProvider) message,
|
||||
message.getReplacements(getManager().getLocales(), this));
|
||||
} else {
|
||||
var formatter = getManager().getFormat(messageType);
|
||||
if (formatter != null) {
|
||||
sendMessage(formatter.format(message.formatted(getManager().getLocales(), this)));
|
||||
} else {
|
||||
sendMessage(message.formatted(getManager().getLocales(), this));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command;
|
||||
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import io.vavr.control.Option;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
import org.mvplugins.multiverse.core.permissions.CorePermissionsChecker;
|
||||
import org.mvplugins.multiverse.core.permissions.PermissionUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static org.mvplugins.multiverse.core.permissions.CorePermissionsChecker.*;
|
||||
|
||||
/**
|
||||
* Maps permission checking to custom logic for commands, to allow more complex permission checking.
|
||||
*/
|
||||
@Service
|
||||
public class MVCommandPermissions {
|
||||
private final Map<String, Predicate<CommandIssuer>> permissionsCheckMap;
|
||||
|
||||
@Inject
|
||||
MVCommandPermissions(@NotNull CorePermissionsChecker permissionsChecker) {
|
||||
this.permissionsCheckMap = new HashMap<>();
|
||||
|
||||
registerPermissionChecker("mvteleport", issuer -> permissionsChecker.hasAnyTeleportPermission(issuer.getIssuer()));
|
||||
registerPermissionChecker("mvteleportother", issuer -> permissionsChecker.hasAnyTeleportPermission(issuer.getIssuer(), Scope.OTHER));
|
||||
registerPermissionChecker("mvspawn", issuer -> permissionsChecker.hasAnySpawnPermission(issuer.getIssuer()));
|
||||
registerPermissionChecker("mvspawnother", issuer -> permissionsChecker.hasAnySpawnPermission(issuer.getIssuer(), Scope.OTHER));
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a custom permission checker callback. Use `@id-name` in {@link CommandPermission} decorator to use
|
||||
* the callback instead of the default permission string checking.
|
||||
*
|
||||
* @param id The permission id
|
||||
* @param checker The permission checker callback
|
||||
*/
|
||||
public void registerPermissionChecker(String id, Predicate<CommandIssuer> checker) {
|
||||
permissionsCheckMap.put(prepareId(id), checker);
|
||||
}
|
||||
|
||||
private static @NotNull String prepareId(String id) {
|
||||
return (id.startsWith("@") ? "" : "@") + id.toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the issuer has the given permission.
|
||||
* @param issuer The issuer
|
||||
* @param permission The permission to check
|
||||
* @return True if the issuer has the permission
|
||||
*/
|
||||
boolean hasPermission(CommandIssuer issuer, String permission) {
|
||||
return Option.of(permissionsCheckMap.get(permission))
|
||||
.map(checker -> checker.test(issuer))
|
||||
.getOrElse(() -> PermissionUtils.hasPermission(issuer.getIssuer(), permission));
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command;
|
||||
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
import co.aikar.commands.ExceptionHandler;
|
||||
import co.aikar.commands.RegisteredCommand;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Default handler that will print the stack trace when the command throws an exception.
|
||||
*/
|
||||
public class MVDefaultExceptionHandler implements ExceptionHandler {
|
||||
@Override
|
||||
public boolean execute(BaseCommand command, RegisteredCommand registeredCommand, CommandIssuer sender, List<String> args, Throwable t) {
|
||||
Logging.severe("Failed to execute command /%s %s %s",
|
||||
registeredCommand.getCommand(), registeredCommand.getPrefSubCommand(), String.join(" ", args));
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command;
|
||||
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import co.aikar.commands.BukkitCommandManager;
|
||||
import co.aikar.commands.BukkitRootCommand;
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
import org.mvplugins.multiverse.core.utils.StringFormatter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MVRootCommand extends BukkitRootCommand {
|
||||
protected MVRootCommand(BukkitCommandManager manager, String name) {
|
||||
super(manager, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseCommand execute(CommandIssuer sender, String commandLabel, String[] args) {
|
||||
String[] quoteFormatedArgs = StringFormatter.parseQuotesInArgs(args).toArray(String[]::new);
|
||||
return super.execute(sender, commandLabel, quoteFormatedArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletions(CommandIssuer sender, String alias, String[] args, boolean commandsOnly, boolean isAsync) {
|
||||
String[] quoteFormatedArgs = StringFormatter.parseQuotesInArgs(args).toArray(String[]::new);
|
||||
return super.getTabCompletions(sender, alias, quoteFormatedArgs, commandsOnly, isAsync)
|
||||
.stream()
|
||||
.map(StringFormatter::quoteMultiWordString)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command;
|
||||
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Contract;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagGroup;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
|
||||
/**
|
||||
* Base class for all Multiverse commands.
|
||||
*/
|
||||
@Contract
|
||||
public abstract class MultiverseCommand extends BaseCommand {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.context;
|
||||
|
||||
/**
|
||||
* Simple wrapper for game rule value, as they may be different types.
|
||||
*/
|
||||
public record GameRuleValue(Object value) {
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.context;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* Wrapper for context that get location from player if executed by player,
|
||||
* else requires user input of location coordinates.
|
||||
*
|
||||
* @param value The location
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public record PlayerLocation(Location value) {
|
||||
}
|
||||
-203
@@ -1,203 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.context.issueraware;
|
||||
|
||||
import co.aikar.commands.BukkitCommandExecutionContext;
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.InvalidCommandArgument;
|
||||
import co.aikar.commands.contexts.IssuerAwareContextResolver;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Reusable logic of issuer only and issuer aware context resolvers
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public final class IssuerAwareContextBuilder<T> {
|
||||
|
||||
private BiFunction<BukkitCommandExecutionContext, Player, T> fromPlayer;
|
||||
private BiFunction<BukkitCommandExecutionContext, String, T> fromInput;
|
||||
private Function<BukkitCommandExecutionContext, Message> issuerOnlyFailMessage = context -> Message.of("This command can only be used by a player.");
|
||||
private BiFunction<BukkitCommandExecutionContext, Player, Message> issuerAwarePlayerFailMessage = (context, player) -> Message.of("Unable to resolve context for player '" + player.getName() + "'.");
|
||||
private BiFunction<BukkitCommandExecutionContext, String, Message> issuerAwareInputFailMessage = (context, input) -> Message.of("Unable to resolve context for input '" + input + "'.");
|
||||
private BiFunction<BukkitCommandExecutionContext, String, Message> inputOnlyFailMessage = (context, input) -> Message.of("Unable to resolve context for input '" + input + "'.");
|
||||
|
||||
public IssuerAwareContextBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse value from player itself.
|
||||
*
|
||||
* @param fromInput the parsing function
|
||||
* @return The same builder for chaining
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public IssuerAwareContextBuilder<T> fromPlayer(BiFunction<BukkitCommandExecutionContext, Player, T> fromInput) {
|
||||
this.fromPlayer = fromInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse value from command input string.
|
||||
*
|
||||
* @param fromInput the parsing function
|
||||
* @return The same builder for chaining
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public IssuerAwareContextBuilder<T> fromInput(BiFunction<BukkitCommandExecutionContext, String, T> fromInput) {
|
||||
this.fromInput = fromInput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When getting value fails as issuer is not a player.
|
||||
*
|
||||
* @param issuerOnlyFailMessage The message
|
||||
* @return The same builder for chaining
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public IssuerAwareContextBuilder<T> issuerOnlyFailMessage(Function<BukkitCommandExecutionContext, Message> issuerOnlyFailMessage) {
|
||||
this.issuerOnlyFailMessage = issuerOnlyFailMessage;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When getting value fails as player cannot parse the value.
|
||||
*
|
||||
* @param issuerAwarePlayerFailMessage The message
|
||||
* @return The same builder for chaining
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public IssuerAwareContextBuilder<T> issuerAwarePlayerFailMessage(BiFunction<BukkitCommandExecutionContext, Player, Message> issuerAwarePlayerFailMessage) {
|
||||
this.issuerAwarePlayerFailMessage = issuerAwarePlayerFailMessage;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When getting value fails as input cannot parse the value.
|
||||
*
|
||||
* @param issuerAwareInputFailMessage The message
|
||||
* @return The same builder for chaining
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public IssuerAwareContextBuilder<T> issuerAwareInputFailMessage(BiFunction<BukkitCommandExecutionContext, String, Message> issuerAwareInputFailMessage) {
|
||||
this.issuerAwareInputFailMessage = issuerAwareInputFailMessage;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When getting value fails as input cannot parse the value.
|
||||
*
|
||||
* @param inputOnlyFailMessage The message
|
||||
* @return The same builder for chaining
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public IssuerAwareContextBuilder<T> inputOnlyFailMessage(BiFunction<BukkitCommandExecutionContext, String, Message> inputOnlyFailMessage) {
|
||||
this.inputOnlyFailMessage = inputOnlyFailMessage;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the issuer aware context resolver logic.
|
||||
*
|
||||
* @return The generated context resolver
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public IssuerAwareContextResolver<T, BukkitCommandExecutionContext> generateContext() {
|
||||
validateRequiredVariables();
|
||||
return context -> resolveValue(context, GenericIssuerAwareValue::new).value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the issuer aware context resolver logic, with marking of whether the value was resolved from player or input.
|
||||
*
|
||||
* @param createValue The function to create the {@link IssuerAwareValue} value
|
||||
* @param <I> The type of the value
|
||||
* @return The generated context resolver
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public <I extends IssuerAwareValue> IssuerAwareContextResolver<I, BukkitCommandExecutionContext> generateContext(BiFunction<Boolean, T, I> createValue) {
|
||||
validateRequiredVariables();
|
||||
return context -> resolveValue(context, createValue);
|
||||
}
|
||||
|
||||
private void validateRequiredVariables() {
|
||||
Objects.requireNonNull(fromPlayer);
|
||||
Objects.requireNonNull(fromInput);
|
||||
Objects.requireNonNull(issuerOnlyFailMessage);
|
||||
Objects.requireNonNull(issuerAwarePlayerFailMessage);
|
||||
Objects.requireNonNull(issuerAwareInputFailMessage);
|
||||
Objects.requireNonNull(inputOnlyFailMessage);
|
||||
}
|
||||
|
||||
private <I extends IssuerAwareValue> I resolveValue(BukkitCommandExecutionContext context, BiFunction<Boolean, T, I> createValue) {
|
||||
BukkitCommandIssuer issuer = context.getIssuer();
|
||||
String resolve = context.getFlagValue("resolve", "");
|
||||
|
||||
if (resolve.equals("issuerOnly")) {
|
||||
if (issuer.isPlayer()) {
|
||||
T result = fromPlayer.apply(context, issuer.getPlayer());
|
||||
if (result != null) {
|
||||
return createValue.apply(true, result);
|
||||
}
|
||||
}
|
||||
throw new InvalidCommandArgument(issuerOnlyFailMessage.apply(context).formatted(issuer));
|
||||
}
|
||||
|
||||
String input = context.getFirstArg();
|
||||
T result = fromInput.apply(context, input);
|
||||
if (result != null) {
|
||||
context.popFirstArg();
|
||||
return createValue.apply(false, result);
|
||||
}
|
||||
|
||||
int maxArgForAware = context.getFlagValue("maxArgForAware", Integer.MAX_VALUE);
|
||||
long argLengthWithoutFlags = context.getArgs().stream()
|
||||
.takeWhile(value -> !value.startsWith("-") && !value.isEmpty()) // ignore the flags
|
||||
.count();
|
||||
|
||||
if (resolve.equals("issuerAware") && argLengthWithoutFlags <= maxArgForAware) {
|
||||
if (issuer.isPlayer()) {
|
||||
Player player = issuer.getPlayer();
|
||||
result = fromPlayer.apply(context, player);
|
||||
if (result != null) {
|
||||
return createValue.apply(true, result);
|
||||
}
|
||||
throw new InvalidCommandArgument(issuerAwarePlayerFailMessage.apply(context, player).formatted(issuer));
|
||||
}
|
||||
throw new InvalidCommandArgument(issuerAwareInputFailMessage.apply(context, input).formatted(issuer));
|
||||
}
|
||||
|
||||
throw new InvalidCommandArgument(inputOnlyFailMessage.apply(context, input).formatted(issuer));
|
||||
}
|
||||
|
||||
private static class GenericIssuerAwareValue<T> extends IssuerAwareValue {
|
||||
private final T value;
|
||||
|
||||
public GenericIssuerAwareValue(boolean byIssuer, T value) {
|
||||
super(byIssuer);
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.context.issueraware;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* Base class for issuer aware values
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public abstract class IssuerAwareValue {
|
||||
protected final boolean byIssuer;
|
||||
|
||||
/**
|
||||
* Constructor to create an issuer aware value
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
protected IssuerAwareValue(boolean byIssuer) {
|
||||
this.byIssuer = byIssuer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the value is by issuer or input
|
||||
*
|
||||
* @return true if by issuer, false if by input
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public boolean isByIssuer() {
|
||||
return byIssuer;
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.context.issueraware;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
|
||||
/**
|
||||
* Issuer aware value wrapper for {@link MultiverseWorld}
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public final class MultiverseWorldValue extends IssuerAwareValue {
|
||||
|
||||
private final MultiverseWorld world;
|
||||
|
||||
/**
|
||||
* Constructor for issuer aware value
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public MultiverseWorldValue(boolean byIssuer, MultiverseWorld world) {
|
||||
super(byIssuer);
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
/**
|
||||
* The containing world wrapped
|
||||
*
|
||||
* @return wrapped world
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public MultiverseWorld value() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.context.issueraware;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* Issuer aware value wrapper for {@link Player} array
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public final class PlayerArrayValue extends IssuerAwareValue {
|
||||
|
||||
private final Player[] players;
|
||||
|
||||
/**
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public PlayerArrayValue(boolean byIssuer, Player[] players) {
|
||||
super(byIssuer);
|
||||
this.players = players;
|
||||
}
|
||||
|
||||
/**
|
||||
* The containing player array wrapped
|
||||
*
|
||||
* @return wrapped player array
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
@ApiStatus.AvailableSince("5.1")
|
||||
public Player[] value() {
|
||||
return players;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.context;
|
||||
@@ -1,61 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.flag;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Contract;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Builds and registers a flag group on initialization. Flags should be final fields that calls {@link #flag(CommandFlag)}.
|
||||
*/
|
||||
@Contract
|
||||
public abstract class FlagBuilder {
|
||||
|
||||
private final String name;
|
||||
private final CommandFlagsManager flagsManager;
|
||||
private final List<CommandFlag> flags;
|
||||
|
||||
protected FlagBuilder(@NotNull String name, @NotNull CommandFlagsManager flagsManager) {
|
||||
this.name = name;
|
||||
this.flagsManager = flagsManager;
|
||||
this.flags = new ArrayList<>();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void postConstruct() {
|
||||
CommandFlagGroup.Builder flagGroupBuilder = CommandFlagGroup.builder(name);
|
||||
flags.forEach(flagGroupBuilder::add);
|
||||
registerFlagGroup(flagGroupBuilder.build());
|
||||
}
|
||||
|
||||
private void registerFlagGroup(@NotNull CommandFlagGroup flagGroup) {
|
||||
flagsManager.registerFlagGroup(flagGroup);
|
||||
Logging.finer("Registered flag group: " + flagGroup.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new flag to the flag builder.
|
||||
*
|
||||
* @param flag The flag to add.
|
||||
* @param <T> The type of the flag.
|
||||
* @return The flag.
|
||||
*/
|
||||
protected <T extends CommandFlag> T flag(T flag) {
|
||||
flags.add(flag);
|
||||
Logging.finer("Added flag: " + flag);
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses flags.
|
||||
*
|
||||
* @param flags The raw string array to parse into flags.
|
||||
* @return The parsed flags.
|
||||
*/
|
||||
public @NotNull ParsedCommandFlags parse(@NotNull String[] flags) {
|
||||
return flagsManager.parse(name, flags);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* This package contains classes related to parsing command flags.
|
||||
*/
|
||||
package org.mvplugins.multiverse.core.command.flag;
|
||||
@@ -1,41 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.flags;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import co.aikar.commands.InvalidCommandArgument;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.display.filters.ContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.filters.RegexContentFilter;
|
||||
|
||||
/**
|
||||
* A command flag for regex filtering.
|
||||
* <br/>
|
||||
* Parses the value of the --filter (or -f) flag as a {@link ContentFilter}.
|
||||
*/
|
||||
public final class FilterCommandFlag extends CommandValueFlag<ContentFilter> {
|
||||
|
||||
private static final Function<String, ContentFilter> VALUE_PARSER = value -> {
|
||||
try {
|
||||
return RegexContentFilter.fromString(value);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new InvalidCommandArgument("Invalid filter: " + value);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new instance of this flag.
|
||||
*
|
||||
* @return The new instance.
|
||||
*/
|
||||
@NotNull
|
||||
public static FilterCommandFlag create() {
|
||||
return new FilterCommandFlag();
|
||||
}
|
||||
|
||||
private FilterCommandFlag() {
|
||||
super("--filter", List.of("-f"), ContentFilter.class, false, null, VALUE_PARSER, null);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.flags;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandValueFlag;
|
||||
|
||||
/**
|
||||
* A command flag for page number.
|
||||
* <br/>
|
||||
* Parses the value of the --page (or -p) flag as an integer.
|
||||
*/
|
||||
public final class PageCommandFlag extends CommandValueFlag<Integer> {
|
||||
|
||||
private static final Function<String, Integer> VALUE_PARSER = value -> {
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("Invalid page number: " + value);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new instance of this flag.
|
||||
*
|
||||
* @return The new instance.
|
||||
*/
|
||||
@NotNull
|
||||
public static PageCommandFlag create() {
|
||||
return new PageCommandFlag();
|
||||
}
|
||||
|
||||
private PageCommandFlag() {
|
||||
super("--page", List.of("-p"), Integer.class, false, null, VALUE_PARSER, null);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.flags;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.FlagBuilder;
|
||||
import org.mvplugins.multiverse.core.display.filters.ContentFilter;
|
||||
|
||||
@Service
|
||||
public class PageFilterFlags extends FlagBuilder {
|
||||
|
||||
public static final String NAME = "pagefilter";
|
||||
|
||||
protected PageFilterFlags(@NotNull String name, @NotNull CommandFlagsManager flagsManager) {
|
||||
super(name, flagsManager);
|
||||
}
|
||||
|
||||
@Inject
|
||||
protected PageFilterFlags(@NotNull CommandFlagsManager flagsManager) {
|
||||
super(NAME, flagsManager);
|
||||
}
|
||||
|
||||
public final CommandValueFlag<Integer> page = flag(PageCommandFlag.create());
|
||||
|
||||
public final CommandValueFlag<ContentFilter> filter = flag(FilterCommandFlag.create());
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.flags;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.FlagBuilder;
|
||||
|
||||
@Service
|
||||
public class RemovePlayerFlags extends FlagBuilder {
|
||||
|
||||
public static final String NAME = "removeplayer";
|
||||
|
||||
protected RemovePlayerFlags(@NotNull String name, @NotNull CommandFlagsManager flagsManager) {
|
||||
super(name, flagsManager);
|
||||
}
|
||||
|
||||
@Inject
|
||||
protected RemovePlayerFlags(@NotNull CommandFlagsManager flagsManager) {
|
||||
super(NAME, flagsManager);
|
||||
}
|
||||
|
||||
public final CommandFlag removePlayers = flag(CommandFlag.builder("--remove-players")
|
||||
.addAlias("-r")
|
||||
.build());
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.flags;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.FlagBuilder;
|
||||
|
||||
@Service
|
||||
public class UnsafeFlags extends FlagBuilder {
|
||||
|
||||
public static final String NAME = "unsafe";
|
||||
|
||||
protected UnsafeFlags(@NotNull String name, @NotNull CommandFlagsManager flagsManager) {
|
||||
super(name, flagsManager);
|
||||
}
|
||||
|
||||
@Inject
|
||||
protected UnsafeFlags(@NotNull CommandFlagsManager flagsManager) {
|
||||
super(NAME, flagsManager);
|
||||
}
|
||||
|
||||
public final CommandFlag unsafe = flag(CommandFlag.builder("--unsafe")
|
||||
.addAlias("-u")
|
||||
.build());
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* This package contains predefined flags for commands.
|
||||
*/
|
||||
package org.mvplugins.multiverse.core.command.flags;
|
||||
@@ -1,192 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Multiverse 2 Copyright (c) the Multiverse Team 2020. *
|
||||
* Multiverse 2 is licensed under the BSD License. *
|
||||
* For more information please check the README.md file included *
|
||||
* with this project. *
|
||||
******************************************************************************/
|
||||
|
||||
package org.mvplugins.multiverse.core.command.queue;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import io.vavr.control.Option;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.data.type.CommandBlock;
|
||||
import org.bukkit.command.BlockCommandSender;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.MultiverseCore;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.config.CoreConfig;
|
||||
import org.mvplugins.multiverse.core.utils.result.Attempt;
|
||||
|
||||
import static org.mvplugins.multiverse.core.locale.message.MessageReplacement.*;
|
||||
|
||||
/**
|
||||
* <p>Manages the queuing of dangerous commands that require {@code /mv confirm} before executing.</p>
|
||||
*
|
||||
* <p>Each sender can only have one command in queue at any given time. When a queued command is added
|
||||
* for a sender that already has a command in queue, it will replace the old queued command.</p>
|
||||
*/
|
||||
@Service
|
||||
public class CommandQueueManager {
|
||||
|
||||
private static final String CONSOLE_NAME = "@console";
|
||||
private static final String COMMAND_BLOCK_NAME = "@commandblock";
|
||||
private static final long TICKS_PER_SECOND = 20;
|
||||
|
||||
private final Plugin plugin;
|
||||
private final CoreConfig config;
|
||||
private final Map<String, CommandQueuePayload> queuedCommandMap;
|
||||
|
||||
@Inject
|
||||
CommandQueueManager(@NotNull MultiverseCore plugin, @NotNull CoreConfig config) {
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
this.queuedCommandMap = new WeakHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link CommandQueuePayload} into queue.
|
||||
*
|
||||
* @param payload The command queue payload to add.
|
||||
*/
|
||||
public void addToQueue(CommandQueuePayload payload) {
|
||||
String senderName = parseSenderName(payload.issuer());
|
||||
if (canRunImmediately(senderName)) {
|
||||
payload.action().run();
|
||||
return;
|
||||
}
|
||||
|
||||
this.removeFromQueue(senderName);
|
||||
|
||||
Logging.finer("Add new command to queue for sender %s.", senderName);
|
||||
this.queuedCommandMap.put(senderName, payload);
|
||||
payload.expireTask(runExpireLater(senderName, config.getConfirmTimeout()));
|
||||
|
||||
payload.issuer().sendInfo(payload.prompt());
|
||||
var confirmCommand = "/mv confirm";
|
||||
if (config.getUseConfirmOtp()) {
|
||||
confirmCommand += " " + payload.otp();
|
||||
}
|
||||
payload.issuer().sendMessage(String.format("Run %s%s %sto continue. This will expire in %s seconds.",
|
||||
ChatColor.GREEN, confirmCommand, ChatColor.WHITE, config.getConfirmTimeout()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if sender does not need to queue before running.
|
||||
*
|
||||
* @param senderName The name of sender.
|
||||
* @return True if sender does not need to queue before running.
|
||||
*/
|
||||
private boolean canRunImmediately(@NotNull String senderName) {
|
||||
return switch (config.getConfirmMode()) {
|
||||
case ENABLE -> false;
|
||||
case PLAYER_ONLY -> senderName.equals(CONSOLE_NAME) || senderName.equals(COMMAND_BLOCK_NAME);
|
||||
case DISABLE_COMMAND_BLOCKS -> senderName.equals(COMMAND_BLOCK_NAME);
|
||||
case DISABLE_CONSOLE -> senderName.equals(CONSOLE_NAME);
|
||||
case DISABLE -> true;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Expire task that removes a {@link CommandQueuePayload} from queue after valid duration defined.
|
||||
*
|
||||
* @param senderName The name of the sender.
|
||||
* @return The expire {@link BukkitTask}.
|
||||
*/
|
||||
@NotNull
|
||||
private BukkitTask runExpireLater(@NotNull String senderName, int validDuration) {
|
||||
return Bukkit.getScheduler().runTaskLater(
|
||||
this.plugin,
|
||||
expireRunnable(senderName),
|
||||
validDuration * TICKS_PER_SECOND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runnable responsible for expiring the queued command.
|
||||
*
|
||||
* @param senderName The name of the sender.
|
||||
* @return The expire runnable.
|
||||
*/
|
||||
@NotNull
|
||||
private Runnable expireRunnable(@NotNull String senderName) {
|
||||
return () -> {
|
||||
CommandQueuePayload payload = this.queuedCommandMap.remove(senderName);
|
||||
if (payload == null) {
|
||||
// Payload already removed
|
||||
return;
|
||||
}
|
||||
payload.issuer().sendMessage("Your queued command has expired.");
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the command in queue for the given sender, if any.
|
||||
*
|
||||
* @param issuer Sender that confirmed the command.
|
||||
* @return True if queued command ran successfully, else false.
|
||||
*/
|
||||
public Attempt<Void, RunQueuedFailedReason> runQueuedCommand(@NotNull MVCommandIssuer issuer, String otpInput) {
|
||||
String senderName = parseSenderName(issuer);
|
||||
return Option.of(this.queuedCommandMap.get(senderName)).fold(
|
||||
() -> Attempt.failure(RunQueuedFailedReason.NO_COMMAND_IN_QUEUE),
|
||||
payload -> runPayload(senderName, otpInput, payload));
|
||||
}
|
||||
|
||||
private Attempt<Void, RunQueuedFailedReason> runPayload(String senderName, String otpInput, CommandQueuePayload payload) {
|
||||
if (config.getUseConfirmOtp() && !Objects.equals(payload.otp(), otpInput)) {
|
||||
return Attempt.failure(RunQueuedFailedReason.INVALID_OTP, replace("{otp}").with(otpInput));
|
||||
}
|
||||
this.removeFromQueue(senderName);
|
||||
Logging.finer("Running queued command...");
|
||||
payload.action().run();
|
||||
return Attempt.success(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Since only one command is stored in queue per sender, we remove the old one.
|
||||
*
|
||||
* @param senderName The sender that executed the command.
|
||||
*/
|
||||
public void removeFromQueue(@NotNull String senderName) {
|
||||
CommandQueuePayload payload = this.queuedCommandMap.remove(senderName);
|
||||
if (payload == null) {
|
||||
Logging.finer("No queue command to remove for sender %s.", senderName);
|
||||
return;
|
||||
}
|
||||
Option.of(payload.expireTask()).peek(BukkitTask::cancel);
|
||||
Logging.finer("Removed queue command for sender %s.", senderName);
|
||||
}
|
||||
|
||||
private String parseSenderName(MVCommandIssuer issuer) {
|
||||
CommandSender sender = issuer.getIssuer();
|
||||
if (isCommandBlock(sender)) {
|
||||
return COMMAND_BLOCK_NAME;
|
||||
} else if (sender instanceof ConsoleCommandSender) {
|
||||
return CONSOLE_NAME;
|
||||
}
|
||||
return sender.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the sender is a command block.
|
||||
*
|
||||
* @param sender The sender to check.
|
||||
* @return True if sender is a command block, else false.
|
||||
*/
|
||||
private boolean isCommandBlock(@NotNull CommandSender sender) {
|
||||
return sender instanceof BlockCommandSender
|
||||
&& ((BlockCommandSender) sender).getBlock().getBlockData() instanceof CommandBlock;
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.queue;
|
||||
|
||||
import co.aikar.commands.ACFUtil;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
|
||||
/**
|
||||
* Represents a single command used in {@link CommandQueueManager} for confirming before running potentially
|
||||
* dangerous action.
|
||||
*/
|
||||
public class CommandQueuePayload {
|
||||
|
||||
/**
|
||||
* Creates a new {@link CommandQueuePayload}
|
||||
*
|
||||
* @param issuer The issuer of the command
|
||||
* @return The new {@link CommandQueuePayload}
|
||||
*/
|
||||
public static CommandQueuePayload issuer(@NotNull MVCommandIssuer issuer) {
|
||||
return new CommandQueuePayload(issuer);
|
||||
}
|
||||
|
||||
private static final String DEFAULT_PROMPT_MESSAGE = "The command you are trying to run is deemed dangerous."; // todo: localize
|
||||
|
||||
private final MVCommandIssuer issuer;
|
||||
private String otp;
|
||||
private Runnable action = () -> {};
|
||||
private Message prompt = Message.of(DEFAULT_PROMPT_MESSAGE);
|
||||
private BukkitTask expireTask;
|
||||
|
||||
protected CommandQueuePayload(@NotNull MVCommandIssuer issuer) {
|
||||
this.otp = String.valueOf(ACFUtil.rand(100, 999));
|
||||
this.issuer = issuer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the issuer of the command.
|
||||
* @return The issuer
|
||||
*/
|
||||
@NotNull
|
||||
public MVCommandIssuer issuer() {
|
||||
return issuer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logic to execute upon confirming.
|
||||
* @param action The logic to execute
|
||||
* @return The same {@link CommandQueuePayload} for method chaining
|
||||
*/
|
||||
public CommandQueuePayload action(@NotNull Runnable action) {
|
||||
this.action = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the logic to execute upon confirming.
|
||||
*
|
||||
* @return The logic to execute
|
||||
*/
|
||||
@NotNull
|
||||
public Runnable action() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the OTP number for validation.
|
||||
*
|
||||
* @param otp The OTP number
|
||||
* @return The same {@link CommandQueuePayload} for method chaining
|
||||
*/
|
||||
public CommandQueuePayload otp(String otp) {
|
||||
this.otp = otp;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the OTP number for validation.
|
||||
*
|
||||
* @return The OTP number
|
||||
*/
|
||||
public String otp() {
|
||||
return otp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the question to ask sender to confirm.
|
||||
*
|
||||
* @param prompt The prompt message.
|
||||
* @return The same {@link CommandQueuePayload} for method chaining.
|
||||
*/
|
||||
public CommandQueuePayload prompt(Message prompt) {
|
||||
this.prompt = prompt;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the question to ask sender to confirm.
|
||||
*
|
||||
* @return The prompt message.
|
||||
*/
|
||||
public Message prompt() {
|
||||
return prompt;
|
||||
}
|
||||
|
||||
void expireTask(BukkitTask expireTask) {
|
||||
this.expireTask = expireTask;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
BukkitTask expireTask() {
|
||||
return expireTask;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.queue;
|
||||
|
||||
/**
|
||||
* Sets whether the command executor needs to confirm before executing a command.
|
||||
*/
|
||||
public enum ConfirmMode {
|
||||
/**
|
||||
* Every command executor needs to confirm before executing a command.
|
||||
*/
|
||||
ENABLE,
|
||||
|
||||
/**
|
||||
* Only players need to confirm before executing a command. Command blocks and console will not need to confirm.
|
||||
*/
|
||||
PLAYER_ONLY,
|
||||
|
||||
/**
|
||||
* Everyone except command blocks will not need to confirm before executing a command.
|
||||
*/
|
||||
DISABLE_COMMAND_BLOCKS,
|
||||
|
||||
/**
|
||||
* Everyone except console will not need to confirm before executing a command.
|
||||
*/
|
||||
DISABLE_CONSOLE,
|
||||
|
||||
/**
|
||||
* Everyone will not need to confirm before executing a command.
|
||||
*/
|
||||
DISABLE,
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.command.queue;
|
||||
|
||||
import co.aikar.locales.MessageKey;
|
||||
import co.aikar.locales.MessageKeyProvider;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.utils.result.FailureReason;
|
||||
|
||||
public enum RunQueuedFailedReason implements FailureReason {
|
||||
NO_COMMAND_IN_QUEUE(MVCorei18n.QUEUECOMMAND_NOCOMMANDINQUEUE),
|
||||
INVALID_OTP(MVCorei18n.QUEUECOMMAND_INVALIDOTP),
|
||||
COMMAND_EXECUTION_ERROR(MVCorei18n.QUEUECOMMAND_COMMANDEXECUTIONERROR),
|
||||
;
|
||||
|
||||
private final MessageKeyProvider message;
|
||||
|
||||
RunQueuedFailedReason(MessageKeyProvider message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public MessageKey getMessageKey() {
|
||||
return message.getMessageKey();
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.anchor.AnchorManager;
|
||||
import org.mvplugins.multiverse.core.anchor.MultiverseAnchor;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
|
||||
@Service
|
||||
final class AnchorDeleteCommand extends CoreCommand {
|
||||
|
||||
private final AnchorManager anchorManager;
|
||||
|
||||
@Inject
|
||||
AnchorDeleteCommand(@NotNull AnchorManager anchorManager) {
|
||||
this.anchorManager = anchorManager;
|
||||
}
|
||||
|
||||
@Subcommand("anchor delete")
|
||||
@CommandPermission("multiverse.core.anchor.delete")
|
||||
@CommandCompletion("@anchornames")
|
||||
@Syntax("<name>")
|
||||
@Description("")
|
||||
void onAnchorDeleteCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Syntax("<name>")
|
||||
@Description("")
|
||||
MultiverseAnchor anchor) {
|
||||
if (anchorManager.deleteAnchor(anchor).isSuccess()) {
|
||||
issuer.sendMessage("&aAnchor &f" + anchor.getName() + "&a deleted.");
|
||||
} else {
|
||||
issuer.sendMessage("&cFailed to delete anchor.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.anchor.AnchorManager;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.PageFilterFlags;
|
||||
import org.mvplugins.multiverse.core.display.ContentDisplay;
|
||||
import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.handlers.PagedSendHandler;
|
||||
import org.mvplugins.multiverse.core.display.parsers.ListContentProvider;
|
||||
import org.mvplugins.multiverse.core.teleportation.LocationManipulation;
|
||||
|
||||
@Service
|
||||
final class AnchorListCommand extends CoreCommand {
|
||||
|
||||
private final AnchorManager anchorManager;
|
||||
private final LocationManipulation locationManipulation;
|
||||
private final PageFilterFlags flags;
|
||||
|
||||
@Inject
|
||||
AnchorListCommand(
|
||||
@NotNull AnchorManager anchorManager,
|
||||
@NotNull LocationManipulation locationManipulation,
|
||||
@NotNull PageFilterFlags flags
|
||||
) {
|
||||
this.anchorManager = anchorManager;
|
||||
this.locationManipulation = locationManipulation;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Subcommand("anchor list")
|
||||
@CommandPermission("multiverse.core.anchor.list")
|
||||
@CommandCompletion("@flags:groupName=" + PageFilterFlags.NAME)
|
||||
@Syntax("[--page <page>] [--filter <filter>]")
|
||||
@Description("")
|
||||
void onAnchorListCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--page <page>] [--filter <filter>]")
|
||||
@Description("")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
ContentDisplay.create()
|
||||
.addContent(ListContentProvider.forContent(getAnchors(issuer.getPlayer())))
|
||||
.withSendHandler(PagedSendHandler.create()
|
||||
.withHeader("&3==== [ Multiverse Anchors ] ====")
|
||||
.doPagination(true)
|
||||
.withTargetPage(parsedFlags.flagValue(flags.page, 1))
|
||||
.withFilter(parsedFlags.flagValue(flags.filter, DefaultContentFilter.get())))
|
||||
.send(issuer);
|
||||
}
|
||||
|
||||
private List<String> getAnchors(Player player) {
|
||||
return anchorManager.getAnchors(player).stream()
|
||||
.map(anchor ->
|
||||
"&a%s&7 - &f%s".formatted(
|
||||
anchor.getName(), locationManipulation.locationToString(anchor.getLocation())))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Single;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.anchor.AnchorManager;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.teleportation.LocationManipulation;
|
||||
|
||||
@Service
|
||||
final class AnchorSetCommand extends CoreCommand {
|
||||
|
||||
private final AnchorManager anchorManager;
|
||||
private final LocationManipulation locationManipulation;
|
||||
|
||||
@Inject
|
||||
AnchorSetCommand(
|
||||
@NotNull AnchorManager anchorManager,
|
||||
@NotNull LocationManipulation locationManipulation
|
||||
) {
|
||||
this.anchorManager = anchorManager;
|
||||
this.locationManipulation = locationManipulation;
|
||||
}
|
||||
|
||||
@Subcommand("anchor set")
|
||||
@CommandPermission("multiverse.core.anchor.create")
|
||||
@CommandCompletion("@empty @locations")
|
||||
@Syntax("<name> [location]")
|
||||
@Description("")
|
||||
void onAnchorSetCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerOnly")
|
||||
Player player,
|
||||
|
||||
@Single
|
||||
@Syntax("<name>")
|
||||
@Description("")
|
||||
//TODO: Check if anchor name is valid or exists already.
|
||||
String anchorName) {
|
||||
Location anchorLocation = player.getLocation();
|
||||
if (anchorManager.setAnchor(anchorName, anchorLocation).isSuccess()) {
|
||||
sendAnchorSetSuccessMessage(issuer, anchorName, locationManipulation.locationToString(anchorLocation));
|
||||
} else {
|
||||
sendAnchorSetFailedMessage(issuer, anchorName);
|
||||
}
|
||||
}
|
||||
|
||||
@Subcommand("anchor set")
|
||||
@CommandPermission("multiverse.core.anchor.create")
|
||||
@CommandCompletion("@anchornames @locations")
|
||||
@Syntax("<name> [location]")
|
||||
@Description("")
|
||||
void onAnchorSetCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Syntax("<name>")
|
||||
@Description("")
|
||||
String anchorName,
|
||||
|
||||
@Single
|
||||
@Syntax("[location]")
|
||||
@Description("")
|
||||
String locationString) {
|
||||
if (anchorManager.setAnchor(anchorName, locationString).isSuccess()) {
|
||||
sendAnchorSetSuccessMessage(issuer, anchorName, locationString);
|
||||
} else {
|
||||
sendAnchorSetFailedMessage(issuer, anchorName);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendAnchorSetSuccessMessage(MVCommandIssuer issuer, String anchorName, String locationString) {
|
||||
issuer.sendMessage("&aAnchor &f" + anchorName + "&a set to &f" + locationString);
|
||||
}
|
||||
|
||||
private void sendAnchorSetFailedMessage(MVCommandIssuer issuer, String anchorName) {
|
||||
issuer.sendMessage("&cFailed to set anchor &f" + anchorName + ".");
|
||||
}
|
||||
}
|
||||
@@ -11,35 +11,28 @@ import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.destination.DestinationInstance;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.permissions.CorePermissionsChecker;
|
||||
import org.mvplugins.multiverse.core.teleportation.LocationManipulation;
|
||||
|
||||
import static org.mvplugins.multiverse.core.locale.message.MessageReplacement.replace;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
|
||||
import org.mvplugins.multiverse.core.destination.ParsedDestination;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
|
||||
@Service
|
||||
class CheckCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class CheckCommand extends MultiverseCommand {
|
||||
|
||||
private final CorePermissionsChecker corePermissionsChecker;
|
||||
private final LocationManipulation locationManipulation;
|
||||
private final DestinationsProvider destinationsProvider;
|
||||
|
||||
@Inject
|
||||
CheckCommand(
|
||||
@NotNull CorePermissionsChecker corePermissionsChecker,
|
||||
@NotNull LocationManipulation locationManipulation
|
||||
) {
|
||||
this.corePermissionsChecker = corePermissionsChecker;
|
||||
this.locationManipulation = locationManipulation;
|
||||
CheckCommand(@NotNull MVCommandManager commandManager, @NotNull DestinationsProvider destinationsProvider) {
|
||||
super(commandManager);
|
||||
this.destinationsProvider = destinationsProvider;
|
||||
}
|
||||
|
||||
@Subcommand("check")
|
||||
@CommandPermission("multiverse.core.check")
|
||||
@CommandCompletion("@players @destinations")
|
||||
@CommandCompletion("@players @destinations|@mvworlds")
|
||||
@Syntax("<player> <destination>")
|
||||
@Description("{@@mv-core.check.description}")
|
||||
void onCheckCommand(
|
||||
@@ -51,32 +44,11 @@ class CheckCommand extends CoreCommand {
|
||||
|
||||
@Syntax("<destination>")
|
||||
@Description("{@@mv-core.check.destination.description}")
|
||||
DestinationInstance<?, ?> destination) {
|
||||
issuer.sendInfo(this.corePermissionsChecker.checkTeleportPermission(player, player, destination)
|
||||
? MVCorei18n.CHECK_HASPERMISSION
|
||||
: MVCorei18n.CHECK_NOPERMISSION,
|
||||
Replace.PLAYER.with(player.getName()),
|
||||
Replace.DESTINATION.with(destination));
|
||||
issuer.sendInfo(MVCorei18n.CHECK_LOCATION,
|
||||
replace("{location}").with(destination.getLocation(player)
|
||||
.map(locationManipulation::locationToString)
|
||||
.map(Message::of)
|
||||
.getOrElse(() -> Message.of(MVCorei18n.GENERIC_NULL, "Null!"))));
|
||||
|
||||
// TODO: Show permission required for this particular destination
|
||||
}
|
||||
|
||||
@Service
|
||||
private final static class LegacyAlias extends CheckCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull CorePermissionsChecker corePermissionsChecker, @NotNull LocationManipulation locationManipulation) {
|
||||
super(corePermissionsChecker, locationManipulation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvcheck")
|
||||
void onCheckCommand(MVCommandIssuer issuer, Player player, DestinationInstance<?, ?> destination) {
|
||||
super.onCheckCommand(issuer, player, destination);
|
||||
}
|
||||
ParsedDestination<?> destination) {
|
||||
issuer.sendInfo(MVCorei18n.CHECK_CHECKING,
|
||||
"{player}", player.getName(),
|
||||
"{destination}", destination.toString());
|
||||
// TODO: More detailed output on permissions required.
|
||||
this.destinationsProvider.checkTeleportPermissions(issuer, player, destination);
|
||||
}
|
||||
}
|
||||
@@ -12,36 +12,44 @@ import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.FlagBuilder;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.options.CloneWorldOptions;
|
||||
|
||||
import static org.mvplugins.multiverse.core.locale.message.MessageReplacement.replace;
|
||||
|
||||
@Service
|
||||
class CloneCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class CloneCommand extends MultiverseCommand {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
private final CloneCommand.Flags flags;
|
||||
|
||||
private final CommandFlag RESET_WORLD_CONFIG_FLAG = flag(CommandFlag.builder("--reset-world-config")
|
||||
.addAlias("-wc")
|
||||
.build());
|
||||
|
||||
private final CommandFlag RESET_GAMERULES_FLAG = flag(CommandFlag.builder("--reset-gamerules")
|
||||
.addAlias("-gm")
|
||||
.build());
|
||||
|
||||
private final CommandFlag RESET_WORLD_BORDER_FLAG = flag(CommandFlag.builder("--reset-world-border")
|
||||
.addAlias("-wb")
|
||||
.build());
|
||||
|
||||
@Inject
|
||||
CloneCommand(@NotNull WorldManager worldManager, @NotNull Flags flags) {
|
||||
CloneCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Subcommand("clone")
|
||||
@CommandPermission("multiverse.core.clone")
|
||||
@CommandCompletion("@mvworlds:scope=loaded @empty @flags:groupName=" + Flags.NAME)
|
||||
@Syntax("<world> <new-world-name> [--reset-world-config --reset-gamerules --reset-world-border]")
|
||||
@CommandCompletion("@mvworlds:scope=loaded @empty @flags:groupName=mvclonecommand")
|
||||
@Syntax("<world> <new world name>")
|
||||
@Description("{@@mv-core.clone.description}")
|
||||
void onCloneCommand(
|
||||
MVCommandIssuer issuer,
|
||||
@@ -50,72 +58,28 @@ class CloneCommand extends CoreCommand {
|
||||
@Description("{@@mv-core.clone.world.description}")
|
||||
LoadedMultiverseWorld world,
|
||||
|
||||
@Syntax("<new-world-name>")
|
||||
@Syntax("<new world name>")
|
||||
@Description("{@@mv-core.clone.newWorld.description}")
|
||||
String newWorldName,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--reset-world-config --reset-gamerules --reset-world-border]")
|
||||
@Syntax(/* TODO */ "")
|
||||
@Description("{@@mv-core.regen.other.description}")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
String[] flags) {
|
||||
ParsedCommandFlags parsedFlags = parseFlags(flags);
|
||||
|
||||
issuer.sendInfo(MVCorei18n.CLONE_CLONING,
|
||||
Replace.WORLD.with(world.getName()),
|
||||
replace("{newworld}").with(newWorldName));
|
||||
issuer.sendInfo(MVCorei18n.CLONE_CLONING, "{world}", world.getName(), "{newworld}", newWorldName);
|
||||
CloneWorldOptions cloneWorldOptions = CloneWorldOptions.fromTo(world, newWorldName)
|
||||
.keepWorldConfig(!parsedFlags.hasFlag(flags.resetWorldConfig))
|
||||
.keepGameRule(!parsedFlags.hasFlag(flags.resetGamerules))
|
||||
.keepWorldBorder(!parsedFlags.hasFlag(flags.resetWorldBorder))
|
||||
.saveBukkitWorld(!parsedFlags.hasFlag(flags.noSave));
|
||||
.keepWorldConfig(!parsedFlags.hasFlag(RESET_WORLD_CONFIG_FLAG))
|
||||
.keepGameRule(!parsedFlags.hasFlag(RESET_GAMERULES_FLAG))
|
||||
.keepWorldBorder(!parsedFlags.hasFlag(RESET_WORLD_BORDER_FLAG));
|
||||
worldManager.cloneWorld(cloneWorldOptions)
|
||||
.onSuccess(newWorld -> {
|
||||
Logging.fine("World clone success: " + newWorld);
|
||||
issuer.sendInfo(MVCorei18n.CLONE_SUCCESS, Replace.WORLD.with(newWorld.getName()));
|
||||
issuer.sendInfo(MVCorei18n.CLONE_SUCCESS, "{world}", newWorld.getName());
|
||||
}).onFailure(failure -> {
|
||||
Logging.fine("World clone failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class Flags extends FlagBuilder {
|
||||
|
||||
private static final String NAME = "mvclone";
|
||||
|
||||
@Inject
|
||||
private Flags(@NotNull CommandFlagsManager flagsManager) {
|
||||
super(NAME, flagsManager);
|
||||
}
|
||||
|
||||
private final CommandFlag resetWorldConfig = flag(CommandFlag.builder("--reset-world-config")
|
||||
.addAlias("-wc")
|
||||
.build());
|
||||
|
||||
private final CommandFlag resetGamerules = flag(CommandFlag.builder("--reset-gamerules")
|
||||
.addAlias("-gm")
|
||||
.build());
|
||||
|
||||
private final CommandFlag resetWorldBorder = flag(CommandFlag.builder("--reset-world-border")
|
||||
.addAlias("-wb")
|
||||
.build());
|
||||
|
||||
private final CommandFlag noSave = flag(CommandFlag.builder("--no-save")
|
||||
.addAlias("-s")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Service
|
||||
private final static class LegacyAlias extends CloneCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull WorldManager worldManager, @NotNull Flags flags) {
|
||||
super(worldManager, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvcl|mvclone")
|
||||
void onCloneCommand(MVCommandIssuer issuer, LoadedMultiverseWorld world, String newWorldName, String[] flags) {
|
||||
super.onCloneCommand(issuer, world, newWorldName, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,82 +12,61 @@ import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.config.CoreConfig;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.commandtools.context.MVConfigValue;
|
||||
import org.mvplugins.multiverse.core.config.MVCoreConfig;
|
||||
import org.mvplugins.multiverse.core.exceptions.MultiverseException;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
|
||||
@Service
|
||||
class ConfigCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class ConfigCommand extends MultiverseCommand {
|
||||
|
||||
private final CoreConfig config;
|
||||
private final MVCoreConfig config;
|
||||
|
||||
@Inject
|
||||
ConfigCommand(@NotNull CoreConfig config) {
|
||||
ConfigCommand(@NotNull MVCommandManager commandManager, @NotNull MVCoreConfig config) {
|
||||
super(commandManager);
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Subcommand("config")
|
||||
@CommandPermission("multiverse.core.config")
|
||||
@CommandCompletion("@mvconfigs @mvconfigvalues")
|
||||
@Syntax("<name> [value]")
|
||||
@Description("{@@mv-core.config.description}")
|
||||
@CommandCompletion("@mvconfigs")
|
||||
@Syntax("<name> [new-value]")
|
||||
@Description("") // TODO: Description
|
||||
void onConfigCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Syntax("<name>")
|
||||
@Description("{@@mv-core.config.name.description}")
|
||||
@Description("") // TODO: Description
|
||||
String name,
|
||||
|
||||
@Optional
|
||||
@Syntax("[value]")
|
||||
@Description("{@@mv-core.config.value.description}")
|
||||
String value) {
|
||||
@Syntax("[new-value]")
|
||||
@Description("") // TODO: Description
|
||||
MVConfigValue value) {
|
||||
if (value == null) {
|
||||
showConfigValue(issuer, name);
|
||||
return;
|
||||
}
|
||||
updateConfigValue(issuer, name, value);
|
||||
updateConfigValue(issuer, name, value.getValue());
|
||||
}
|
||||
|
||||
private void showConfigValue(MVCommandIssuer issuer, String name) {
|
||||
config.getStringPropertyHandle().getProperty(name)
|
||||
.onSuccess(value -> issuer.sendMessage(MVCorei18n.CONFIG_SHOW_SUCCESS,
|
||||
Replace.NAME.with(name),
|
||||
Replace.VALUE.with(value)))
|
||||
.onFailure(e -> issuer.sendMessage(MVCorei18n.CONFIG_SHOW_ERROR,
|
||||
Replace.NAME.with(name),
|
||||
Replace.ERROR.with(e)));
|
||||
config.getProperty(name)
|
||||
.onSuccess(value -> issuer.sendMessage(name + "is currently set to " + value))
|
||||
.onFailure(e -> issuer.sendMessage(e.getMessage()));
|
||||
}
|
||||
|
||||
private void updateConfigValue(MVCommandIssuer issuer, String name, String value) {
|
||||
var stringPropertyHandle = config.getStringPropertyHandle();
|
||||
stringPropertyHandle.setPropertyString(issuer.getIssuer(), name, value)
|
||||
.andThenTry(config::save)
|
||||
.onSuccess(ignore -> issuer.sendMessage(MVCorei18n.CONFIG_SET_SUCCESS,
|
||||
Replace.NAME.with(name),
|
||||
Replace.VALUE.with(stringPropertyHandle.getProperty(name).getOrNull())))
|
||||
.onFailure(e -> issuer.sendMessage(MVCorei18n.CONFIG_SET_ERROR,
|
||||
Replace.NAME.with(name),
|
||||
Replace.VALUE.with(value),
|
||||
Replace.ERROR.with(e)));
|
||||
}
|
||||
|
||||
@Service
|
||||
private final static class LegacyAlias extends ConfigCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull CoreConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvconfig|mvconf")
|
||||
void onConfigCommand(MVCommandIssuer issuer, String name, String value) {
|
||||
super.onConfigCommand(issuer, name, value);
|
||||
}
|
||||
private void updateConfigValue(MVCommandIssuer issuer, String name, Object value) {
|
||||
config.setProperty(name, value)
|
||||
.onSuccess(ignore -> {
|
||||
config.save();
|
||||
issuer.sendMessage("Successfully set " + name + " to " + value);
|
||||
})
|
||||
.onFailure(ignore -> issuer.sendMessage("Unable to set " + name + " to " + value + "."))
|
||||
.onFailure(MultiverseException.class, e -> Option.of(e.getMVMessage()).peek(issuer::sendError));
|
||||
}
|
||||
}
|
||||
@@ -1,54 +1,30 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Default;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.queue.CommandQueueManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
|
||||
@Service
|
||||
class ConfirmCommand extends CoreCommand {
|
||||
|
||||
@NotNull
|
||||
private final CommandQueueManager commandQueueManager;
|
||||
@CommandAlias("mv")
|
||||
class ConfirmCommand extends MultiverseCommand {
|
||||
|
||||
@Inject
|
||||
ConfirmCommand(@NotNull CommandQueueManager commandQueueManager) {
|
||||
this.commandQueueManager = commandQueueManager;
|
||||
ConfirmCommand(@NotNull MVCommandManager commandManager) {
|
||||
super(commandManager);
|
||||
}
|
||||
|
||||
@Subcommand("confirm")
|
||||
@CommandPermission("multiverse.core.confirm")
|
||||
@Syntax("[otp]")
|
||||
@Description("{@@mv-core.confirm.description}")
|
||||
void onConfirmCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Default("0")
|
||||
String otp) {
|
||||
this.commandQueueManager.runQueuedCommand(issuer, otp)
|
||||
.onFailure(failure -> issuer.sendError(failure.getFailureMessage()));
|
||||
}
|
||||
|
||||
@Service
|
||||
private final static class LegacyAlias extends ConfirmCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull CommandQueueManager commandQueueCommand) {
|
||||
super(commandQueueCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvconfirm")
|
||||
void onConfirmCommand(MVCommandIssuer issuer, String otp) {
|
||||
super.onConfirmCommand(issuer, otp);
|
||||
}
|
||||
void onConfirmCommand(@NotNull BukkitCommandIssuer issuer) {
|
||||
this.commandManager.getCommandQueueManager().runQueuedCommand(issuer.getIssuer());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
@@ -10,60 +11,42 @@ import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.teleportation.LocationManipulation;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
|
||||
import static org.mvplugins.multiverse.core.locale.message.MessageReplacement.replace;
|
||||
import org.mvplugins.multiverse.core.api.LocationManipulation;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
|
||||
@Service
|
||||
class CoordinatesCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class CoordinatesCommand extends MultiverseCommand {
|
||||
|
||||
private final LocationManipulation locationManipulation;
|
||||
|
||||
@Inject
|
||||
CoordinatesCommand(@NotNull LocationManipulation locationManipulation) {
|
||||
CoordinatesCommand(
|
||||
@NotNull MVCommandManager commandManager,
|
||||
@NotNull LocationManipulation locationManipulation) {
|
||||
super(commandManager);
|
||||
this.locationManipulation = locationManipulation;
|
||||
}
|
||||
|
||||
@Subcommand("coordinates")
|
||||
@Subcommand("coordinates|coords|coord|co")
|
||||
@CommandPermission("multiverse.core.coord")
|
||||
@Description("{@@mv-core.coordinates.description}")
|
||||
void onCoordinatesCommand(
|
||||
MVCommandIssuer issuer,
|
||||
BukkitCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerOnly")
|
||||
Player player,
|
||||
|
||||
@Flags("resolve=issuerOnly")
|
||||
MultiverseWorld world) {
|
||||
LoadedMultiverseWorld world) {
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_TITLE);
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_WORLD, Replace.WORLD.with(world.getName()));
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_ALIAS, replace("{alias}").with(world.getAliasOrName()));
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_WORLDSCALE,
|
||||
replace("{scale}").with(String.valueOf(world.getScale())));
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_COORDINATES,
|
||||
replace("{coordinates}").with(locationManipulation.strCoords(player.getLocation())));
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_DIRECTION,
|
||||
replace("{direction}").with(locationManipulation.getDirection(player.getLocation())));
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends CoordinatesCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull LocationManipulation locationManipulation) {
|
||||
super(locationManipulation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvcoord|mvco")
|
||||
@Subcommand("coords|coord|co")
|
||||
void onCoordinatesCommand(MVCommandIssuer issuer, Player player, MultiverseWorld world) {
|
||||
super.onCoordinatesCommand(issuer, player, world);
|
||||
}
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_WORLD, "{world}", world.getName());
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_ALIAS, "{alias}", world.getAlias());
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_WORLDSCALE, "{scale}", String.valueOf(world.getScale()));
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_COORDINATES, "{coordinates}", locationManipulation.strCoords(player.getLocation()));
|
||||
issuer.sendInfo(MVCorei18n.COORDINATES_INFO_DIRECTION, "{direction}", locationManipulation.getDirection(player.getLocation()));
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Contract;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.command.MultiverseCommand;
|
||||
|
||||
/**
|
||||
* Represents a command that is part of the Multiverse-Core plugin.
|
||||
*/
|
||||
@Contract
|
||||
@CommandAlias("mv")
|
||||
public abstract class CoreCommand extends MultiverseCommand {
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
|
||||
import co.aikar.commands.ACFUtil;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
@@ -17,43 +17,62 @@ import org.bukkit.WorldType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.FlagBuilder;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.utils.result.Attempt.Failure;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.biomeprovider.BiomeProviderFactory;
|
||||
import org.mvplugins.multiverse.core.world.generators.GeneratorProvider;
|
||||
import org.mvplugins.multiverse.core.world.options.CreateWorldOptions;
|
||||
import org.mvplugins.multiverse.core.world.reasons.CreateFailureReason;
|
||||
|
||||
import static org.mvplugins.multiverse.core.locale.message.MessageReplacement.replace;
|
||||
|
||||
@Service
|
||||
class CreateCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class CreateCommand extends MultiverseCommand {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
private final CreateCommand.Flags flags;
|
||||
private GeneratorProvider generatorProvider;
|
||||
|
||||
private final CommandValueFlag<String> SEED_FLAG = flag(CommandValueFlag.builder("--seed", String.class)
|
||||
.addAlias("-s")
|
||||
.completion(input -> Collections.singleton(String.valueOf(new Random().nextLong())))
|
||||
.build());
|
||||
|
||||
private final CommandValueFlag<String> GENERATOR_FLAG = flag(CommandValueFlag
|
||||
.builder("--generator", String.class)
|
||||
.addAlias("-g")
|
||||
.completion(input -> generatorProvider.suggestGeneratorString(input))
|
||||
.build());
|
||||
|
||||
private final CommandValueFlag<WorldType> WORLD_TYPE_FLAG = flag(CommandValueFlag
|
||||
.enumBuilder("--world-type", WorldType.class)
|
||||
.addAlias("-t")
|
||||
.build());
|
||||
|
||||
private final CommandFlag NO_ADJUST_SPAWN_FLAG = flag(CommandFlag.builder("--no-adjust-spawn")
|
||||
.addAlias("-n")
|
||||
.build());
|
||||
|
||||
private final CommandFlag NO_STRUCTURES_FLAG = flag(CommandFlag.builder("--no-structures")
|
||||
.addAlias("-a")
|
||||
.build());
|
||||
|
||||
@Inject
|
||||
CreateCommand(@NotNull WorldManager worldManager, @NotNull Flags flags) {
|
||||
CreateCommand(
|
||||
@NotNull MVCommandManager commandManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull GeneratorProvider generatorProvider) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
this.flags = flags;
|
||||
this.generatorProvider = generatorProvider;
|
||||
}
|
||||
|
||||
@Subcommand("create")
|
||||
@CommandPermission("multiverse.core.create")
|
||||
@CommandCompletion("@empty @environments @flags:groupName=" + Flags.NAME)
|
||||
@Syntax("<name> <environment> [--seed <seed> --generator <generator[:id]> --world-type <worldtype> --adjust-spawn "
|
||||
+ "--no-structures --biome <biome>]")
|
||||
@CommandCompletion("@empty @flags:groupName=mvcreatecommand")
|
||||
@Syntax("<name> <environment> --seed [seed] --generator [generator[:id]] --world-type [worldtype] --adjust-spawn --no-structures")
|
||||
@Description("{@@mv-core.create.description}")
|
||||
void onCreateCommand(
|
||||
MVCommandIssuer issuer,
|
||||
@@ -67,132 +86,41 @@ class CreateCommand extends CoreCommand {
|
||||
World.Environment environment,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--seed <seed> --generator <generator[:id]> --world-type <worldtype> --adjust-spawn "
|
||||
+ "--no-structures --biome <biome>]")
|
||||
@Syntax("--seed [seed] --generator [generator[:id]] --world-type [worldtype] --adjust-spawn --no-structures")
|
||||
@Description("{@@mv-core.create.flags.description}")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
String[] flags) {
|
||||
ParsedCommandFlags parsedFlags = parseFlags(flags);
|
||||
|
||||
messageWorldDetails(issuer, worldName, environment, parsedFlags);
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES,
|
||||
"{worldName}", worldName);
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_ENVIRONMENT,
|
||||
"{environment}", environment.name());
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_SEED,
|
||||
"{seed}", parsedFlags.flagValue(SEED_FLAG, "RANDOM"));
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_WORLDTYPE,
|
||||
"{worldType}", parsedFlags.flagValue(WORLD_TYPE_FLAG, WorldType.NORMAL).name());
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_ADJUSTSPAWN,
|
||||
"{adjustSpawn}", String.valueOf(!parsedFlags.hasFlag(NO_ADJUST_SPAWN_FLAG)));
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_GENERATOR,
|
||||
"{generator}", parsedFlags.flagValue(GENERATOR_FLAG, ""));
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_STRUCTURES,
|
||||
"{structures}", String.valueOf(!parsedFlags.hasFlag(NO_STRUCTURES_FLAG)));
|
||||
|
||||
issuer.sendInfo(MVCorei18n.CREATE_LOADING);
|
||||
|
||||
worldManager.createWorld(CreateWorldOptions.worldName(worldName)
|
||||
.biome(parsedFlags.flagValue(flags.biome, ""))
|
||||
.environment(environment)
|
||||
.seed(parsedFlags.flagValue(flags.seed))
|
||||
.worldType(parsedFlags.flagValue(flags.worldType, WorldType.NORMAL))
|
||||
.useSpawnAdjust(!parsedFlags.hasFlag(flags.noAdjustSpawn))
|
||||
.generator(parsedFlags.flagValue(flags.generator, ""))
|
||||
.generatorSettings(parsedFlags.flagValue(flags.generatorSettings, ""))
|
||||
.generateStructures(!parsedFlags.hasFlag(flags.noStructures)))
|
||||
.onSuccess(newWorld -> messageSuccess(issuer, newWorld))
|
||||
.onFailure(failure -> messageFailure(issuer, failure));
|
||||
}
|
||||
|
||||
private void messageWorldDetails(MVCommandIssuer issuer, String worldName,
|
||||
World.Environment environment, ParsedCommandFlags parsedFlags) {
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES,
|
||||
replace("{worldName}").with(worldName));
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_ENVIRONMENT,
|
||||
replace("{environment}").with(environment.name()));
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_SEED,
|
||||
replace("{seed}").with(parsedFlags.flagValue(flags.seed, "RANDOM")));
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_WORLDTYPE,
|
||||
replace("{worldType}").with(parsedFlags.flagValue(flags.worldType, WorldType.NORMAL).name()));
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_ADJUSTSPAWN,
|
||||
replace("{adjustSpawn}").with(String.valueOf(!parsedFlags.hasFlag(flags.noAdjustSpawn))));
|
||||
if (parsedFlags.hasFlag(flags.biome)) {
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_BIOME,
|
||||
replace("{biome}").with(parsedFlags.flagValue(flags.biome)));
|
||||
}
|
||||
if (parsedFlags.hasFlag(flags.generator)) {
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_GENERATOR,
|
||||
replace("{generator}").with(parsedFlags.flagValue(flags.generator)));
|
||||
}
|
||||
if (parsedFlags.hasFlag(flags.generatorSettings)) {
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_GENERATORSETTINGS,
|
||||
replace("{generatorSettings}").with(parsedFlags.flagValue(flags.generatorSettings)));
|
||||
}
|
||||
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_STRUCTURES,
|
||||
replace("{structures}").with(String.valueOf(!parsedFlags.hasFlag(flags.noStructures))));
|
||||
}
|
||||
|
||||
private void messageSuccess(MVCommandIssuer issuer, LoadedMultiverseWorld newWorld) {
|
||||
Logging.fine("World create success: " + newWorld);
|
||||
issuer.sendInfo(MVCorei18n.CREATE_SUCCESS, Replace.WORLD.with(newWorld.getName()));
|
||||
}
|
||||
|
||||
private void messageFailure(MVCommandIssuer issuer, Failure<LoadedMultiverseWorld, CreateFailureReason> failure) {
|
||||
Logging.fine("World create failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class Flags extends FlagBuilder {
|
||||
|
||||
private static final String NAME = "mvcreate";
|
||||
|
||||
private GeneratorProvider generatorProvider;
|
||||
private BiomeProviderFactory biomeProviderFactory;
|
||||
|
||||
@Inject
|
||||
private Flags(
|
||||
@NotNull CommandFlagsManager flagsManager,
|
||||
@NotNull GeneratorProvider generatorProvider,
|
||||
@NotNull BiomeProviderFactory biomeProviderFactory
|
||||
) {
|
||||
super(NAME, flagsManager);
|
||||
this.generatorProvider = generatorProvider;
|
||||
this.biomeProviderFactory = biomeProviderFactory;
|
||||
}
|
||||
|
||||
private final CommandValueFlag<String> seed = flag(CommandValueFlag.builder("--seed", String.class)
|
||||
.addAlias("-s")
|
||||
.completion(input -> Collections.singleton(String.valueOf(ACFUtil.RANDOM.nextLong())))
|
||||
.build());
|
||||
|
||||
private final CommandValueFlag<String> generator = flag(CommandValueFlag
|
||||
.builder("--generator", String.class)
|
||||
.addAlias("-g")
|
||||
.completion(input -> generatorProvider.suggestGeneratorString(input))
|
||||
.build());
|
||||
|
||||
private final CommandValueFlag<String> generatorSettings = flag(CommandValueFlag
|
||||
.builder("--generator-settings", String.class)
|
||||
.addAlias("-gs")
|
||||
.build());
|
||||
|
||||
private final CommandValueFlag<WorldType> worldType = flag(CommandValueFlag
|
||||
.enumBuilder("--world-type", WorldType.class)
|
||||
.addAlias("-t")
|
||||
.build());
|
||||
|
||||
private final CommandFlag noAdjustSpawn = flag(CommandFlag.builder("--no-adjust-spawn")
|
||||
.addAlias("-n")
|
||||
.build());
|
||||
|
||||
private final CommandFlag noStructures = flag(CommandFlag.builder("--no-structures")
|
||||
.addAlias("-a")
|
||||
.build());
|
||||
|
||||
private final CommandValueFlag<String> biome = flag(CommandValueFlag.builder("--biome", String.class)
|
||||
.addAlias("-b")
|
||||
.completion(input -> biomeProviderFactory.suggestBiomeString(input))
|
||||
.build());
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends CreateCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull WorldManager worldManager, @NotNull Flags flags) {
|
||||
super(worldManager, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvcreate|mvc")
|
||||
void onCreateCommand(MVCommandIssuer issuer, String worldName, World.Environment environment, String[] flags) {
|
||||
super.onCreateCommand(issuer, worldName, environment, flags);
|
||||
}
|
||||
.seed(parsedFlags.flagValue(SEED_FLAG))
|
||||
.worldType(parsedFlags.flagValue(WORLD_TYPE_FLAG, WorldType.NORMAL))
|
||||
.useSpawnAdjust(!parsedFlags.hasFlag(NO_ADJUST_SPAWN_FLAG))
|
||||
.generator(parsedFlags.flagValue(GENERATOR_FLAG, ""))
|
||||
.generateStructures(!parsedFlags.hasFlag(NO_STRUCTURES_FLAG)))
|
||||
.onSuccess(newWorld -> {
|
||||
Logging.fine("World create success: " + newWorld);
|
||||
issuer.sendInfo(MVCorei18n.CREATE_SUCCESS, "{world}", newWorld.getName());
|
||||
}).onFailure(failure -> {
|
||||
Logging.fine("World create failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -12,18 +12,20 @@ import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.config.CoreConfig;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.config.MVCoreConfig;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
|
||||
@Service
|
||||
class DebugCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class DebugCommand extends MultiverseCommand {
|
||||
|
||||
private final CoreConfig config;
|
||||
private final MVCoreConfig config;
|
||||
|
||||
@Inject
|
||||
DebugCommand(@NotNull CoreConfig config) {
|
||||
DebugCommand(@NotNull MVCommandManager commandManager, @NotNull MVCoreConfig config) {
|
||||
super(commandManager);
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@@ -60,18 +62,4 @@ class DebugCommand extends CoreCommand {
|
||||
issuer.sendInfo(MVCorei18n.DEBUG_INFO_ON, "{level}", String.valueOf(debugLevel));
|
||||
Logging.fine("Multiverse Debug ENABLED.");
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends DebugCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
public LegacyAlias(@NotNull CoreConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvdebug")
|
||||
void onChangeDebugCommand(BukkitCommandIssuer issuer, int level) {
|
||||
super.onChangeDebugCommand(issuer, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import co.aikar.commands.MessageType;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Conditions;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Single;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
@@ -13,114 +14,51 @@ import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.RemovePlayerFlags;
|
||||
import org.mvplugins.multiverse.core.command.queue.CommandQueueManager;
|
||||
import org.mvplugins.multiverse.core.command.queue.CommandQueuePayload;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.utils.WorldTickDeferrer;
|
||||
import org.mvplugins.multiverse.core.utils.result.AsyncAttemptsAggregate;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.commandtools.queue.QueuedCommand;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.helpers.PlayerWorldTeleporter;
|
||||
import org.mvplugins.multiverse.core.world.options.DeleteWorldOptions;
|
||||
|
||||
@Service
|
||||
class DeleteCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class DeleteCommand extends MultiverseCommand {
|
||||
|
||||
private final CommandQueueManager commandQueueManager;
|
||||
private final WorldManager worldManager;
|
||||
private final PlayerWorldTeleporter playerWorldTeleporter;
|
||||
private final WorldTickDeferrer worldTickDeferrer;
|
||||
private final RemovePlayerFlags flags;
|
||||
|
||||
@Inject
|
||||
DeleteCommand(
|
||||
@NotNull CommandQueueManager commandQueueManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull PlayerWorldTeleporter playerWorldTeleporter,
|
||||
@NotNull WorldTickDeferrer worldTickDeferrer,
|
||||
@NotNull RemovePlayerFlags flags
|
||||
) {
|
||||
this.commandQueueManager = commandQueueManager;
|
||||
DeleteCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
this.playerWorldTeleporter = playerWorldTeleporter;
|
||||
this.worldTickDeferrer = worldTickDeferrer;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Subcommand("delete")
|
||||
@CommandPermission("multiverse.core.delete")
|
||||
@CommandCompletion("@mvworlds:scope=both @flags:groupName=" + RemovePlayerFlags.NAME)
|
||||
@CommandCompletion("@mvworlds:scope=both")
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.delete.description}")
|
||||
void onDeleteCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Single
|
||||
@Conditions("worldname:scope=both")
|
||||
@Syntax("<world>")
|
||||
@Description("The world you want to delete.")
|
||||
MultiverseWorld world,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--remove-players]")
|
||||
@Description("")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
|
||||
commandQueueManager.addToQueue(CommandQueuePayload
|
||||
.issuer(issuer)
|
||||
.action(() -> runDeleteCommand(issuer, world, parsedFlags))
|
||||
.prompt(Message.of(MVCorei18n.DELETE_PROMPT, "",
|
||||
Replace.WORLD.with(world.getName()))));
|
||||
}
|
||||
|
||||
private void runDeleteCommand(MVCommandIssuer issuer, MultiverseWorld world, ParsedCommandFlags parsedFlags) {
|
||||
issuer.sendInfo(MVCorei18n.DELETE_DELETING, Replace.WORLD.with(world.getName()));
|
||||
|
||||
var future = parsedFlags.hasFlag(flags.removePlayers)
|
||||
&& world.isLoaded()
|
||||
&& world instanceof LoadedMultiverseWorld loadedWorld
|
||||
? playerWorldTeleporter.removeFromWorld(loadedWorld)
|
||||
: AsyncAttemptsAggregate.emptySuccess();
|
||||
|
||||
future.onSuccess(() -> worldTickDeferrer.deferWorldTick(() -> doWorldDeleting(issuer, world)))
|
||||
.onFailure(() -> issuer.sendError("Failed to teleport one or more players out of the world!"));
|
||||
}
|
||||
|
||||
private void doWorldDeleting(MVCommandIssuer issuer, MultiverseWorld world) {
|
||||
worldManager.deleteWorld(DeleteWorldOptions.world(world))
|
||||
.onSuccess(deletedWorldName -> {
|
||||
Logging.fine("World delete success: " + deletedWorldName);
|
||||
issuer.sendInfo(MVCorei18n.DELETE_SUCCESS, Replace.WORLD.with(deletedWorldName));
|
||||
}).onFailure(failure -> {
|
||||
Logging.fine("World delete failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends DeleteCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(
|
||||
@NotNull CommandQueueManager commandQueueManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull PlayerWorldTeleporter playerWorldTeleporter,
|
||||
@NotNull WorldTickDeferrer worldTickDeferrer,
|
||||
@NotNull RemovePlayerFlags flags) {
|
||||
super(commandQueueManager, worldManager, playerWorldTeleporter, worldTickDeferrer, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvdelete")
|
||||
void onDeleteCommand(MVCommandIssuer issuer, MultiverseWorld world, String[] flags) {
|
||||
super.onDeleteCommand(issuer, world, flags);
|
||||
}
|
||||
String worldName) {
|
||||
this.commandManager.getCommandQueueManager().addToQueue(new QueuedCommand(
|
||||
issuer.getIssuer(),
|
||||
() -> {
|
||||
issuer.sendInfo(MVCorei18n.DELETE_DELETING, "{world}", worldName);
|
||||
worldManager.deleteWorld(worldName)
|
||||
.onSuccess(deletedWorldName -> {
|
||||
Logging.fine("World delete success: " + deletedWorldName);
|
||||
issuer.sendInfo(MVCorei18n.DELETE_SUCCESS, "{world}", deletedWorldName);
|
||||
}).onFailure(failure -> {
|
||||
Logging.fine("World delete failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
}, this.commandManager.formatMessage(
|
||||
issuer, MessageType.INFO, MVCorei18n.DELETE_PROMPT, "{world}", worldName)));
|
||||
}
|
||||
}
|
||||
@@ -1,81 +1,282 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import jakarta.inject.Inject;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.FlagBuilder;
|
||||
import org.mvplugins.multiverse.core.commands.DumpsLogPoster.LogsType;
|
||||
import org.mvplugins.multiverse.core.commands.DumpsLogPoster.UploadType;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.MultiverseCore;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.event.MVVersionEvent;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.utils.webpaste.PasteFailedException;
|
||||
import org.mvplugins.multiverse.core.utils.webpaste.PasteService;
|
||||
import org.mvplugins.multiverse.core.utils.webpaste.PasteServiceFactory;
|
||||
import org.mvplugins.multiverse.core.utils.webpaste.PasteServiceType;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
|
||||
import static org.mvplugins.multiverse.core.utils.file.FileUtils.getBukkitConfig;
|
||||
import static org.mvplugins.multiverse.core.utils.file.FileUtils.getServerProperties;
|
||||
|
||||
@Service
|
||||
final class DumpsCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class DumpsCommand extends MultiverseCommand {
|
||||
|
||||
private final DumpsService dumpsService;
|
||||
private final DumpsCommand.Flags flags;
|
||||
private final MultiverseCore plugin;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
private final CommandValueFlag<LogsTypeOption> LOGS_FLAG = flag(CommandValueFlag
|
||||
.enumBuilder("--logs", LogsTypeOption.class)
|
||||
.addAlias("-l")
|
||||
.build());
|
||||
|
||||
private final CommandValueFlag<ServiceTypeOption> UPLOAD_FLAG = flag(CommandValueFlag
|
||||
.enumBuilder("--upload", ServiceTypeOption.class)
|
||||
.addAlias("-u")
|
||||
.build());
|
||||
|
||||
// Does not upload logs or plugin list (except if --logs mclogs is there)
|
||||
private final CommandFlag PARANOID_FLAG = flag(CommandFlag.builder("--paranoid")
|
||||
.addAlias("-p")
|
||||
.build());
|
||||
|
||||
@Inject
|
||||
DumpsCommand(@NotNull DumpsService dumpsService, @NotNull Flags flags) {
|
||||
this.dumpsService = dumpsService;
|
||||
this.flags = flags;
|
||||
DumpsCommand(@NotNull MVCommandManager commandManager,
|
||||
@NotNull MultiverseCore plugin,
|
||||
@NotNull WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.plugin = plugin;
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
|
||||
private enum ServiceTypeOption {
|
||||
PASTEGG,
|
||||
PASTESDEV
|
||||
}
|
||||
|
||||
private enum LogsTypeOption {
|
||||
APPEND,
|
||||
MCLOGS
|
||||
}
|
||||
|
||||
@Subcommand("dumps")
|
||||
@CommandPermission("multiverse.core.dumps")
|
||||
@CommandCompletion("@flags:groupName=" + Flags.NAME)
|
||||
@CommandCompletion("@flags:groupName=mvdumpscommand")
|
||||
@Syntax("[--logs <mclogs | append>] [--upload <pastesdev | pastegg>] [--paranoid]")
|
||||
@Description("{@@mv-core.dumps.description}")
|
||||
void onDumpsCommand(
|
||||
MVCommandIssuer issuer,
|
||||
CommandIssuer issuer,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--logs <mclogs | append>] [--upload <pastesdev | pastegg>] [--paranoid]")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
String[] flags) {
|
||||
final ParsedCommandFlags parsedFlags = parseFlags(flags);
|
||||
|
||||
// Grab all our flags
|
||||
boolean paranoid = parsedFlags.hasFlag(flags.paranoid);
|
||||
LogsType logsType = parsedFlags.flagValue(flags.logs, LogsType.MCLOGS);
|
||||
UploadType servicesType = parsedFlags.flagValue(flags.upload, UploadType.PASTESDEV);
|
||||
final boolean paranoid = parsedFlags.hasFlag(PARANOID_FLAG);
|
||||
final LogsTypeOption logsType = parsedFlags.flagValue(LOGS_FLAG, LogsTypeOption.MCLOGS);
|
||||
final ServiceTypeOption servicesType = parsedFlags.flagValue(UPLOAD_FLAG, ServiceTypeOption.PASTEGG);
|
||||
|
||||
dumpsService.postLogs(issuer, logsType, servicesType, paranoid);
|
||||
}
|
||||
// Initialise and add info to the debug event
|
||||
MVVersionEvent versionEvent = new MVVersionEvent();
|
||||
this.addDebugInfoToEvent(versionEvent);
|
||||
plugin.getServer().getPluginManager().callEvent(versionEvent);
|
||||
|
||||
@Service
|
||||
private static final class Flags extends FlagBuilder {
|
||||
|
||||
private static final String NAME = "mvdumps";
|
||||
|
||||
@Inject
|
||||
private Flags(@NotNull CommandFlagsManager flagsManager) {
|
||||
super(NAME, flagsManager);
|
||||
// Add plugin list if user isn't paranoid
|
||||
if (!paranoid) {
|
||||
versionEvent.putDetailedVersionInfo("plugins.md", "# Plugins\n\n" + getPluginList());
|
||||
}
|
||||
|
||||
private final CommandValueFlag<LogsType> logs = flag(CommandValueFlag
|
||||
.enumBuilder("--logs", LogsType.class)
|
||||
.addAlias("-l")
|
||||
.build());
|
||||
BukkitRunnable logPoster = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO: Refactor into smaller methods
|
||||
Logging.finer("Logs type is: " + logsType);
|
||||
Logging.finer("Services is: " + servicesType);
|
||||
|
||||
private final CommandValueFlag<UploadType> upload = flag(CommandValueFlag
|
||||
.enumBuilder("--upload", UploadType.class)
|
||||
.addAlias("-u")
|
||||
.build());
|
||||
// Deal with logs flag
|
||||
if (!paranoid) {
|
||||
switch (logsType) {
|
||||
case MCLOGS -> issuer.sendInfo(MVCorei18n.DUMPS_URL_LIST,
|
||||
"{service}", "Logs",
|
||||
"{link}", postToService(PasteServiceType.MCLOGS, true, getLogs(), null));
|
||||
case APPEND -> versionEvent.putDetailedVersionInfo("latest.log", getLogs());
|
||||
}
|
||||
}
|
||||
|
||||
// Does not upload logs or plugin list (except if --logs mclogs is there)
|
||||
private final CommandFlag paranoid = flag(CommandFlag.builder("--paranoid")
|
||||
.addAlias("-p")
|
||||
.build());
|
||||
// Get the files from the event
|
||||
final Map<String, String> files = versionEvent.getDetailedVersionInfo();
|
||||
|
||||
// Deal with uploading debug info
|
||||
switch (servicesType) {
|
||||
case PASTEGG -> issuer.sendInfo(MVCorei18n.DUMPS_URL_LIST,
|
||||
"{service}", "paste.gg",
|
||||
"{link}", postToService(PasteServiceType.PASTEGG, true, null, files));
|
||||
case PASTESDEV -> issuer.sendInfo(MVCorei18n.DUMPS_URL_LIST,
|
||||
"{service}", "pastes.dev",
|
||||
"{link}", postToService(PasteServiceType.PASTESDEV, true, null, files));
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// Run the uploader async as it could take some time to upload the debug info
|
||||
logPoster.runTaskAsynchronously(plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contents of the latest.log file
|
||||
*
|
||||
* @return A string containing the latest.log file
|
||||
*/
|
||||
private String getLogs() {
|
||||
// Get the Path of latest.log
|
||||
Path logsPath = plugin.getServer().getWorldContainer().toPath().resolve("logs").resolve("latest.log");
|
||||
File logsFile = logsPath.toFile();
|
||||
|
||||
if (!logsFile.exists()) {
|
||||
Logging.warning("Could not read logs/latest.log");
|
||||
return "Could not find log";
|
||||
}
|
||||
|
||||
// Try reading as ANSI encoded
|
||||
try {
|
||||
return Files.readString(logsPath, StandardCharsets.ISO_8859_1);
|
||||
} catch (IOException e) {
|
||||
Logging.finer("Log is not ANSI encoded. Trying UTF-8");
|
||||
// Must be a UTF-8 encoded log then
|
||||
}
|
||||
|
||||
// Try reading as UTF-8 encoded
|
||||
try {
|
||||
return Files.readString(logsPath, StandardCharsets.UTF_8);
|
||||
} catch (IOException ex) {
|
||||
// It is some other strange encoding
|
||||
Logging.severe("Could not read ./logs/latest.log. See below for stack trace");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return "Could not read log";
|
||||
}
|
||||
|
||||
private String getVersionString() {
|
||||
return "# Multiverse-Core Version info" + "\n\n"
|
||||
+ " - Multiverse-Core Version: " + this.plugin.getDescription().getVersion() + '\n'
|
||||
+ " - Bukkit Version: " + this.plugin.getServer().getVersion() + '\n'
|
||||
+ " - Loaded Worlds: " + worldManager.getLoadedWorlds() + '\n'
|
||||
+ " - Multiverse Plugins Loaded: " + this.plugin.getPluginCount() + '\n';
|
||||
}
|
||||
|
||||
private void addDebugInfoToEvent(MVVersionEvent event) {
|
||||
// Add the legacy file, but as markdown, so it's readable
|
||||
event.putDetailedVersionInfo("version.md", this.getVersionString());
|
||||
|
||||
// add config.yml
|
||||
File configFile = new File(plugin.getDataFolder(), "config.yml");
|
||||
event.putDetailedVersionInfo("multiverse-core/config.yml", configFile);
|
||||
|
||||
// add worlds.yml
|
||||
File worldsFile = new File(plugin.getDataFolder(), "worlds.yml");
|
||||
event.putDetailedVersionInfo("multiverse-core/worlds.yml", worldsFile);
|
||||
|
||||
// Add bukkit.yml if we found it
|
||||
if (getBukkitConfig() != null) {
|
||||
event.putDetailedVersionInfo(getBukkitConfig().getPath(), getBukkitConfig());
|
||||
} else {
|
||||
Logging.warning("/mv version could not find bukkit.yml. Not including file");
|
||||
}
|
||||
|
||||
// Add server.properties if we found it
|
||||
if (getServerProperties() != null) {
|
||||
event.putDetailedVersionInfo(getServerProperties().getPath(), getServerProperties());
|
||||
} else {
|
||||
Logging.warning("/mv version could not find server.properties. Not including file");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String getPluginList() {
|
||||
return " - " + StringUtils.join(plugin.getServer().getPluginManager().getPlugins(), "\n - ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a list of files in to a string containing askii art.
|
||||
*
|
||||
* @param files Map of filenames/contents
|
||||
* @return The askii art
|
||||
*/
|
||||
private String encodeAsString(Map<String, String> files) {
|
||||
StringBuilder uploadData = new StringBuilder();
|
||||
for (String file : files.keySet()) {
|
||||
String data = files.get(file);
|
||||
uploadData.append("# ---------- ")
|
||||
.append(file)
|
||||
.append(" ----------\n\n")
|
||||
.append(data)
|
||||
.append("\n\n");
|
||||
}
|
||||
|
||||
return uploadData.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the current contents of this.pasteBinBuffer to a web service.
|
||||
*
|
||||
* @param type Service type to send paste data to.
|
||||
* @param isPrivate Should the paste be marked as private.
|
||||
* @param rawPasteData Legacy string containing only data to post to a service.
|
||||
* @param pasteFiles Map of filenames/contents of debug info.
|
||||
* @return URL of visible paste
|
||||
*/
|
||||
private String postToService(@NotNull PasteServiceType type, boolean isPrivate, @Nullable String rawPasteData, @Nullable Map<String, String> pasteFiles) {
|
||||
PasteService pasteService = PasteServiceFactory.getService(type, isPrivate);
|
||||
|
||||
try {
|
||||
// Upload normally when multi file is supported
|
||||
if (pasteService.supportsMultiFile()) {
|
||||
return pasteService.postData(pasteFiles);
|
||||
}
|
||||
|
||||
// When there is raw paste data, use that
|
||||
if (rawPasteData != null) { // For the logs
|
||||
return pasteService.postData(rawPasteData);
|
||||
}
|
||||
|
||||
// If all we have are files and the paste service does not support multi file then encode them
|
||||
if (pasteFiles != null) {
|
||||
return pasteService.postData(this.encodeAsString(pasteFiles));
|
||||
}
|
||||
|
||||
// Should never get here
|
||||
return "No data specified in code";
|
||||
|
||||
} catch (PasteFailedException e) {
|
||||
e.printStackTrace();
|
||||
return "Error posting to service.";
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
return "That service isn't supported yet.";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.event.MVDumpsDebugInfoEvent;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.utils.webpaste.PasteFailedException;
|
||||
import org.mvplugins.multiverse.core.utils.webpaste.PasteService;
|
||||
import org.mvplugins.multiverse.core.utils.webpaste.PasteServiceFactory;
|
||||
import org.mvplugins.multiverse.core.utils.webpaste.PasteServiceType;
|
||||
|
||||
final class DumpsLogPoster extends BukkitRunnable {
|
||||
|
||||
enum UploadType {
|
||||
// BEGIN CHECKSTYLE-SUPPRESSION: JavadocVariable
|
||||
PASTEGG(PasteServiceType.PASTEGG, "paste.gg"),
|
||||
PASTESDEV(PasteServiceType.PASTESDEV, "pastes.dev");
|
||||
// END CHECKSTYLE-SUPPRESSION: JavadocVariable
|
||||
|
||||
private final PasteServiceType pasteServiceType;
|
||||
private final String serviceName;
|
||||
|
||||
UploadType(PasteServiceType pasteServiceType, String serviceName) {
|
||||
this.pasteServiceType = pasteServiceType;
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
}
|
||||
|
||||
enum LogsType {
|
||||
/**
|
||||
* Appends the log file to the debug info.
|
||||
*/
|
||||
APPEND,
|
||||
/**
|
||||
* Uploads the log file to a paste service.
|
||||
*/
|
||||
MCLOGS
|
||||
}
|
||||
|
||||
private final MVCommandIssuer issuer;
|
||||
private final LogsType logsType;
|
||||
private final UploadType uploadType;
|
||||
private final boolean paranoid;
|
||||
private final String logs;
|
||||
private final MVDumpsDebugInfoEvent versionEvent;
|
||||
|
||||
DumpsLogPoster(@NotNull MVCommandIssuer issuer,
|
||||
@NotNull DumpsLogPoster.LogsType logsType,
|
||||
@NotNull DumpsLogPoster.UploadType uploadType,
|
||||
boolean paranoid,
|
||||
@NotNull String logs,
|
||||
@NotNull MVDumpsDebugInfoEvent versionEvent) {
|
||||
this.issuer = issuer;
|
||||
this.logsType = logsType;
|
||||
this.uploadType = uploadType;
|
||||
this.paranoid = paranoid;
|
||||
this.logs = logs;
|
||||
this.versionEvent = versionEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
handleLogs();
|
||||
handleVersionEvent();
|
||||
}
|
||||
|
||||
@SuppressWarnings("checkstyle:MissingSwitchDefault")
|
||||
private void handleLogs() {
|
||||
Logging.finer("Logs type is: " + logsType);
|
||||
|
||||
if (!paranoid) {
|
||||
switch (logsType) {
|
||||
case MCLOGS -> sendDumpsUrl("Logs", postRawDataToMcLogs(logs));
|
||||
case APPEND -> versionEvent.putDetailedDebugInfo("latest.log", logs);
|
||||
default -> Logging.finer("Not uploading logs.");
|
||||
}
|
||||
} else {
|
||||
Logging.finer("Paranoid mode is on, not uploading logs.");
|
||||
}
|
||||
}
|
||||
|
||||
private void handleVersionEvent() {
|
||||
Logging.finer("Upload service is: " + uploadType);
|
||||
|
||||
final Map<String, String> files = versionEvent.getDetailedDebugInfo();
|
||||
sendDumpsUrl(uploadType.serviceName, postFilesToService(files));
|
||||
}
|
||||
|
||||
private void sendDumpsUrl(String service, String url) {
|
||||
issuer.sendInfo(MVCorei18n.DUMPS_URL_LIST, "{service}", service, "{link}", url);
|
||||
}
|
||||
|
||||
private String postRawDataToMcLogs(@NotNull String rawPasteData) {
|
||||
PasteService pasteService = PasteServiceFactory.getService(PasteServiceType.MCLOGS, true);
|
||||
|
||||
return pasteToService(() -> pasteService.postData(rawPasteData));
|
||||
}
|
||||
|
||||
private String postFilesToService(@NotNull Map<String, String> pasteFiles) {
|
||||
PasteService pasteService = PasteServiceFactory.getService(uploadType.pasteServiceType, true);
|
||||
|
||||
return pasteToService(() -> {
|
||||
if (pasteService.supportsMultiFile()) {
|
||||
return pasteService.postData(pasteFiles);
|
||||
} else {
|
||||
return pasteService.postData(this.encodeAsString(pasteFiles));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String encodeAsString(Map<String, String> files) {
|
||||
StringBuilder uploadData = new StringBuilder();
|
||||
for (Map.Entry<String, String> entry : files.entrySet()) {
|
||||
String file = entry.getKey();
|
||||
String data = entry.getValue();
|
||||
uploadData.append("# ---------- ")
|
||||
.append(file)
|
||||
.append(" ----------\n\n")
|
||||
.append(data)
|
||||
.append("\n\n");
|
||||
}
|
||||
|
||||
return uploadData.toString();
|
||||
}
|
||||
|
||||
private String pasteToService(LogPaster paster) {
|
||||
try {
|
||||
return paster.postLogs();
|
||||
} catch (PasteFailedException e) {
|
||||
e.printStackTrace();
|
||||
return "Error posting to service.";
|
||||
}
|
||||
}
|
||||
|
||||
private interface LogPaster {
|
||||
String postLogs() throws PasteFailedException;
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import jakarta.inject.Inject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.MultiverseCore;
|
||||
import org.mvplugins.multiverse.core.module.MultiverseModulesRegistry;
|
||||
import org.mvplugins.multiverse.core.commands.DumpsLogPoster.LogsType;
|
||||
import org.mvplugins.multiverse.core.commands.DumpsLogPoster.UploadType;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.event.MVDumpsDebugInfoEvent;
|
||||
import org.mvplugins.multiverse.core.utils.FileUtils;
|
||||
import org.mvplugins.multiverse.core.utils.StringFormatter;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
|
||||
@Service
|
||||
final class DumpsService {
|
||||
|
||||
private final MultiverseCore plugin;
|
||||
private final WorldManager worldManager;
|
||||
private final FileUtils fileUtils;
|
||||
|
||||
@Inject
|
||||
DumpsService(@NotNull MultiverseCore plugin,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull FileUtils fileUtils) {
|
||||
this.plugin = plugin;
|
||||
this.worldManager = worldManager;
|
||||
this.fileUtils = fileUtils;
|
||||
}
|
||||
|
||||
void postLogs(MVCommandIssuer issuer, LogsType logsType, UploadType servicesType, boolean paranoid) {
|
||||
// Initialise and add info to the debug event
|
||||
MVDumpsDebugInfoEvent versionEvent = createAndCallDebugInfoEvent();
|
||||
|
||||
// Add plugin list if user isn't paranoid
|
||||
if (!paranoid) {
|
||||
versionEvent.putDetailedDebugInfo("plugins.md", "# Plugins\n\n" + getPluginList());
|
||||
}
|
||||
|
||||
new DumpsLogPoster(issuer, logsType, servicesType, paranoid, getLogs(), versionEvent)
|
||||
.runTaskAsynchronously(plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contents of the latest.log file.
|
||||
*
|
||||
* @return A string containing the latest.log file
|
||||
*/
|
||||
private @NotNull String getLogs() {
|
||||
// Get the Path of latest.log
|
||||
Path logsPath = fileUtils.getServerFolder().toPath().resolve("logs/latest.log");
|
||||
File logsFile = logsPath.toFile();
|
||||
|
||||
if (!logsFile.exists()) {
|
||||
Logging.warning("Could not read logs/latest.log");
|
||||
return "Could not find log";
|
||||
}
|
||||
|
||||
return readLogsFromFile(logsPath);
|
||||
}
|
||||
|
||||
private @NotNull String readLogsFromFile(Path logsPath) {
|
||||
String logs = "Could not read log";
|
||||
|
||||
// Try reading as ANSI encoded
|
||||
try {
|
||||
logs = Files.readString(logsPath, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
Logging.severe("Could not read logs/latest.log. See below for stack trace");
|
||||
e.printStackTrace();
|
||||
|
||||
try {
|
||||
logs = Files.readString(logsPath, StandardCharsets.UTF_8);
|
||||
} catch (IOException ex) {
|
||||
// It is some other strange encoding
|
||||
Logging.severe("Could not read ./logs/latest.log. See below for stack trace");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return logs;
|
||||
}
|
||||
|
||||
private String getDebugInfoString() {
|
||||
return "# Multiverse-Core Version info" + "\n\n"
|
||||
+ " - Multiverse-Core Version: " + this.plugin.getDescription().getVersion() + '\n'
|
||||
+ " - Bukkit Version: " + this.plugin.getServer().getVersion() + '\n'
|
||||
+ " - Loaded Worlds: " + worldManager.getLoadedWorlds() + '\n'
|
||||
+ " - Multiverse Plugins Loaded: " + StringFormatter.joinAnd(MultiverseModulesRegistry.get().getRegisteredPlugins()) + '\n'
|
||||
+ " - Multiverse Plugins Count: " + MultiverseModulesRegistry.get().getPluginCount() + '\n';
|
||||
}
|
||||
|
||||
private MVDumpsDebugInfoEvent createAndCallDebugInfoEvent() {
|
||||
MVDumpsDebugInfoEvent event = new MVDumpsDebugInfoEvent();
|
||||
addDebugInfoToEvent(event);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
private void addDebugInfoToEvent(MVDumpsDebugInfoEvent event) {
|
||||
// Add the legacy file, but as markdown, so it's readable
|
||||
event.putDetailedDebugInfo("version.md", this.getDebugInfoString());
|
||||
|
||||
// add config.yml
|
||||
File configFile = new File(plugin.getDataFolder(), "config.yml");
|
||||
event.putDetailedDebugInfo("Multiverse-Core/config.yml", configFile);
|
||||
|
||||
// add worlds.yml
|
||||
File worldsFile = new File(plugin.getDataFolder(), "worlds.yml");
|
||||
event.putDetailedDebugInfo("Multiverse-Core/worlds.yml", worldsFile);
|
||||
|
||||
// Add bukkit.yml if we found it
|
||||
if (fileUtils.getBukkitConfig() != null) {
|
||||
event.putDetailedDebugInfo(fileUtils.getBukkitConfig().getPath(), fileUtils.getBukkitConfig());
|
||||
} else {
|
||||
Logging.warning("/mv dumps could not find bukkit.yml. Not including file");
|
||||
}
|
||||
|
||||
// Add server.properties if we found it
|
||||
if (fileUtils.getServerProperties() != null) {
|
||||
event.putDetailedDebugInfo(fileUtils.getServerProperties().getPath(), fileUtils.getServerProperties());
|
||||
} else {
|
||||
Logging.warning("/mv dumps could not find server.properties. Not including file");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String getPluginList() {
|
||||
return " - " + StringUtils.join(Arrays.stream(plugin.getServer().getPluginManager().getPlugins())
|
||||
.map(Object::toString)
|
||||
.sorted()
|
||||
.toList(), "\n - ");
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Single;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.entity.SpawnCategory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.PageFilterFlags;
|
||||
import org.mvplugins.multiverse.core.config.handle.PropertyModifyAction;
|
||||
import org.mvplugins.multiverse.core.display.ContentDisplay;
|
||||
import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.handlers.PagedSendHandler;
|
||||
import org.mvplugins.multiverse.core.display.parsers.ListContentProvider;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
import org.mvplugins.multiverse.core.utils.StringFormatter;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.entity.SpawnCategoryConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Subcommand("entity-spawn-config")
|
||||
final class EntitySpawnConfigCommand extends CoreCommand {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
private final PageFilterFlags flags;
|
||||
|
||||
@Inject
|
||||
EntitySpawnConfigCommand(@NotNull WorldManager worldManager, @NotNull PageFilterFlags flags) {
|
||||
this.worldManager = worldManager;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Subcommand("info")
|
||||
@CommandPermission("multiverse.core.entityspawnconfig.info")
|
||||
@CommandCompletion("@mvworlds:scope=both|@flags:resolveUntil=arg1,groupName=" + PageFilterFlags.NAME + " @flags:groupName=" + PageFilterFlags.NAME)
|
||||
@Syntax("[world] [--page <page>] [--filter <filter>]")
|
||||
@Description("")
|
||||
void onInfoCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerAware,maxArgForAware=0")
|
||||
@Syntax("[world]")
|
||||
MultiverseWorld world,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--page <page>] [--filter <filter>]")
|
||||
String[] flagArray
|
||||
) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
ContentDisplay.create()
|
||||
.addContent(ListContentProvider.forContent(getEntitySpawnConfigList(world)))
|
||||
.withSendHandler(PagedSendHandler.create()
|
||||
.withHeader(Message.of("==== [ Entity Spawn Config '" + world.getName() + "' ] ===="))
|
||||
.withLinesPerPage(8)
|
||||
.withTargetPage(parsedFlags.flagValue(flags.page, 1))
|
||||
.withFilter(parsedFlags.flagValue(flags.filter, DefaultContentFilter.get())))
|
||||
.send(issuer);
|
||||
}
|
||||
|
||||
private List<String> getEntitySpawnConfigList(MultiverseWorld world) {
|
||||
List<String> list = new ArrayList<>();
|
||||
Arrays.stream(SpawnCategory.values()).forEach(spawnCategory -> {
|
||||
list.add(spawnCategory.name() + ": ");
|
||||
SpawnCategoryConfig spawnCategoryConfig = world.getEntitySpawnConfig().getSpawnCategoryConfig(spawnCategory);
|
||||
list.add(" spawn: " + spawnCategoryConfig.isSpawn());
|
||||
list.add(" tick-rate: " + spawnCategoryConfig.getTickRate());
|
||||
list.add(" exceptions: " + StringFormatter.join(spawnCategoryConfig.getExceptions(), ", "));
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
@Subcommand("modify")
|
||||
@CommandPermission("multiverse.core.entityspawnconfig.modify")
|
||||
@CommandCompletion("@mvworlds:scope=both @spawncategories @propsmodifyaction @spawncategorypropsname @spawncategorypropsvalue")
|
||||
@Syntax("[world] <spawn-category> <set|add|reset|remove> <property> [value]")
|
||||
@Description("")
|
||||
void onModifyCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerAware,maxArgForAware=4")
|
||||
@Syntax("[world]")
|
||||
MultiverseWorld world,
|
||||
|
||||
@Syntax("<spawn-category>")
|
||||
SpawnCategory spawnCategory,
|
||||
|
||||
@Syntax("<set|add|reset|remove>")
|
||||
PropertyModifyAction action,
|
||||
|
||||
@Syntax("<property>")
|
||||
String property,
|
||||
|
||||
@Optional
|
||||
@Single
|
||||
@Syntax("[value]")
|
||||
@Nullable String value
|
||||
) {
|
||||
world.getEntitySpawnConfig()
|
||||
.getSpawnCategoryConfig(spawnCategory)
|
||||
.getStringPropertyHandle()
|
||||
.modifyPropertyString(property, value, action)
|
||||
.andThenTry(worldManager::saveWorldsConfig)
|
||||
.onSuccess(ignore -> issuer.sendInfo("Successfully set " + property + " to " + value
|
||||
+ " for " + spawnCategory.name() + " in " + world.getName()))
|
||||
.onFailure(e -> issuer.sendError("Unable to set " + property + " to " + value
|
||||
+ " for " + spawnCategory.name() + " in " + world.getName() + ": " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -1,233 +1,81 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
import co.aikar.commands.MessageType;
|
||||
import co.aikar.commands.BukkitCommandIssuer;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import io.vavr.control.Option;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.command.context.GameRuleValue;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.PageFilterFlags;
|
||||
import org.mvplugins.multiverse.core.display.ContentDisplay;
|
||||
import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.handlers.PagedSendHandler;
|
||||
import org.mvplugins.multiverse.core.display.parsers.MapContentProvider;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.commandtools.context.GameRuleValue;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
|
||||
import static org.mvplugins.multiverse.core.locale.message.MessageReplacement.replace;
|
||||
|
||||
@Service
|
||||
class GameruleCommand extends CoreCommand {
|
||||
|
||||
private final PageFilterFlags flags;
|
||||
@CommandAlias("mv")
|
||||
class GameruleCommand extends MultiverseCommand {
|
||||
|
||||
@Inject
|
||||
GameruleCommand(@NotNull PageFilterFlags flags) {
|
||||
this.flags = flags;
|
||||
GameruleCommand(@NotNull MVCommandManager commandManager) {
|
||||
super(commandManager);
|
||||
}
|
||||
|
||||
@Subcommand("gamerule|rule set")
|
||||
@Subcommand("gamerule")
|
||||
@CommandPermission("multiverse.core.gamerule.set")
|
||||
@CommandCompletion("@gamerules @gamerulesvalues @mvworlds:multiple|*")
|
||||
@CommandCompletion("@gamerules true|false|@range:1-10 @mvworlds:multiple|*")
|
||||
@Syntax("<Gamerule> <Gamerule value> [World or *]")
|
||||
@Description("{@@mv-core.gamerule.set.description}")
|
||||
void onGameruleSetCommand(
|
||||
MVCommandIssuer issuer,
|
||||
@Description("{@@mv-core.gamerule.description}")
|
||||
void onGameruleCommand(
|
||||
BukkitCommandIssuer issuer,
|
||||
|
||||
@Syntax("<Gamerule>")
|
||||
@Description("{@@mv-core.gamerule.set.gamerule.description}")
|
||||
@Description("{@@mv-core.gamerule.gamerule.description}")
|
||||
GameRule gamerule,
|
||||
|
||||
@Syntax("<Value>")
|
||||
@Description("{@@mv-core.gamerule.set.value.description}")
|
||||
@Description("{@@mv-core.gamerule.value.description}")
|
||||
GameRuleValue gameRuleValue,
|
||||
|
||||
@Flags("resolve=issuerAware,maxArgForAware=2")
|
||||
@Flags("resolve=issuerAware")
|
||||
@Syntax("[World or *]")
|
||||
@Description("{@@mv-core.gamerule.set.world.description}")
|
||||
@Description("{@@mv-core.gamerule.world.description}")
|
||||
LoadedMultiverseWorld[] worlds) {
|
||||
Object value = gameRuleValue.value();
|
||||
Object value = gameRuleValue.getValue();
|
||||
boolean success = true;
|
||||
for (LoadedMultiverseWorld world : worlds) {
|
||||
// Set gamerules and add false to list if it fails
|
||||
World bukkitWorld = world.getBukkitWorld().getOrNull();
|
||||
if (bukkitWorld == null || !bukkitWorld.setGameRule(gamerule, value)) {
|
||||
issuer.sendError(MVCorei18n.GAMERULE_SET_FAILED,
|
||||
Replace.GAMERULE.with(gamerule.getName()),
|
||||
Replace.VALUE.with(value.toString()),
|
||||
Replace.WORLD.with(world.getName()),
|
||||
replace("{type}").with(gamerule.getType().getName()));
|
||||
issuer.sendError(MVCorei18n.GAMERULE_FAILED,
|
||||
"{gamerule}", gamerule.getName(),
|
||||
"{value}", value.toString(),
|
||||
"{world}", world.getName(),
|
||||
"{type}", gamerule.getType().getName());
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
// Tell user if it was successful
|
||||
if (success) {
|
||||
if (worlds.length == 1) {
|
||||
issuer.sendInfo(MVCorei18n.GAMERULE_SET_SUCCESS_SINGLE,
|
||||
Replace.GAMERULE.with(gamerule.getName()),
|
||||
Replace.VALUE.with(value.toString()),
|
||||
Replace.WORLD.with(worlds[0].getName()));
|
||||
issuer.sendInfo(MVCorei18n.GAMERULE_SUCCESS_SINGLE,
|
||||
"{gamerule}", gamerule.getName(),
|
||||
"{value}", value.toString(),
|
||||
"{world}", worlds[0].getName());
|
||||
} else if (worlds.length > 1) {
|
||||
issuer.sendInfo(MVCorei18n.GAMERULE_SET_SUCCESS_MULTIPLE,
|
||||
Replace.GAMERULE.with(gamerule.getName()),
|
||||
Replace.VALUE.with(value.toString()),
|
||||
Replace.COUNT.with(String.valueOf(worlds.length)));
|
||||
issuer.sendInfo(MVCorei18n.GAMERULE_SUCCESS_MULTIPLE,
|
||||
"{gamerule}", gamerule.getName(),
|
||||
"{value}", value.toString(),
|
||||
"{count}", String.valueOf(worlds.length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes,unchecked")
|
||||
@Subcommand("gamerule|rule reset")
|
||||
@CommandPermission("multiverse.core.gamerule.set")
|
||||
@CommandCompletion("@gamerules @mvworlds:multiple|*")
|
||||
@Syntax("<Gamerule> [World or *]")
|
||||
@Description("{@@mv-core.gamerule.reset.description}")
|
||||
void onGameruleResetCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Syntax("<Gamerule>")
|
||||
@Description("{@@mv-core.gamerule.reset.gamerule.description}")
|
||||
GameRule gamerule,
|
||||
|
||||
@Flags("resolve=issuerAware,maxArgForAware=1")
|
||||
@Syntax("[World or *]")
|
||||
@Description("{@@mv-core.gamerule.reset.world.description}")
|
||||
LoadedMultiverseWorld[] worlds) {
|
||||
AtomicBoolean success = new AtomicBoolean(true);
|
||||
Arrays.stream(worlds)
|
||||
.forEach(world -> world.getBukkitWorld()
|
||||
.flatMap(bukkitWorld -> Option.of(bukkitWorld.getGameRuleDefault(gamerule))
|
||||
.map(value -> bukkitWorld.setGameRule(gamerule, value)))
|
||||
.onEmpty(() -> {
|
||||
success.set(false);
|
||||
issuer.sendError(MVCorei18n.GAMERULE_RESET_FAILED,
|
||||
Replace.GAMERULE.with(gamerule.getName()),
|
||||
Replace.WORLD.with(world.getName()));
|
||||
}));
|
||||
|
||||
// Tell user if it was successful
|
||||
if (success.get()) {
|
||||
if (worlds.length == 1) {
|
||||
issuer.sendInfo(MVCorei18n.GAMERULE_RESET_SUCCESS_SINGLE,
|
||||
Replace.GAMERULE.with(gamerule.getName()),
|
||||
Replace.WORLD.with(worlds[0].getName()));
|
||||
} else if (worlds.length > 1) {
|
||||
issuer.sendInfo(MVCorei18n.GAMERULE_RESET_SUCCESS_MULTIPLE,
|
||||
Replace.GAMERULE.with(gamerule.getName()),
|
||||
Replace.COUNT.with(String.valueOf(worlds.length)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subcommand("gamerule|rule list")
|
||||
@CommandPermission("multiverse.core.gamerule.list")
|
||||
@CommandCompletion("@mvworlds|@flags:groupName=" + PageFilterFlags.NAME + " @flags:groupName=" + PageFilterFlags.NAME)
|
||||
@Syntax("[world] [--page <page>] [--filter <filter>]")
|
||||
@Description("{@@mv-core.gamerule.list.description}")
|
||||
void onGameruleListCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerAware,maxArgForAware=0")
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.gamerule.list.description.world}")
|
||||
LoadedMultiverseWorld world,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--page <page>] [--filter <filter>]")
|
||||
@Description("{@@mv-core.gamerule.list.description.page}")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
|
||||
ContentDisplay.create()
|
||||
.addContent(MapContentProvider.forContent(getGameRuleMap(world.getBukkitWorld().getOrNull()))
|
||||
.withKeyColor(ChatColor.AQUA)
|
||||
.withValueColor(ChatColor.WHITE))
|
||||
.withSendHandler(PagedSendHandler.create()
|
||||
.withHeader(this.getListTitle(world.getBukkitWorld().getOrNull()))
|
||||
.doPagination(true)
|
||||
.withTargetPage(parsedFlags.flagValue(flags.page, 1))
|
||||
.withFilter(parsedFlags.flagValue(flags.filter, DefaultContentFilter.get())))
|
||||
.send(issuer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the gamerules and their values for a given world.
|
||||
*
|
||||
* @param world The world to find gamerules for.
|
||||
* @return A map of the gamerules and their values
|
||||
*/
|
||||
private Map<String, String> getGameRuleMap(World world) {
|
||||
Map<String, String> gameRuleMap = new HashMap<>();
|
||||
if (world == null) {
|
||||
return gameRuleMap;
|
||||
}
|
||||
|
||||
for (String gamerule : world.getGameRules()) {
|
||||
GameRule<?> gameruleEnum = GameRule.getByName(gamerule);
|
||||
if (gameruleEnum == null) {
|
||||
continue;
|
||||
}
|
||||
Object gameruleValue = world.getGameRuleValue(gameruleEnum);
|
||||
if (gameruleValue == null) {
|
||||
gameRuleMap.put(gameruleEnum.getName(), "null");
|
||||
continue;
|
||||
}
|
||||
gameRuleMap.put(gameruleEnum.getName(), gameruleValue.toString());
|
||||
}
|
||||
return gameRuleMap;
|
||||
}
|
||||
|
||||
private Message getListTitle(@Nullable World world) {
|
||||
return Message.of(MVCorei18n.GAMERULE_LIST_TITLE, Replace.WORLD.with(world == null ? "null" : world.getName()));
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends GameruleCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull PageFilterFlags flags) {
|
||||
super(flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvrule|mvgamerule")
|
||||
void onGameruleSetCommand(MVCommandIssuer issuer, GameRule gamerule, GameRuleValue gameRuleValue, LoadedMultiverseWorld[] worlds) {
|
||||
super.onGameruleSetCommand(issuer, gamerule, gameRuleValue, worlds);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onGameruleResetCommand(MVCommandIssuer issuer, GameRule gamerule, LoadedMultiverseWorld[] worlds) {
|
||||
super.onGameruleResetCommand(issuer, gamerule, worlds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvrules|mvgamerules")
|
||||
void onGameruleListCommand(MVCommandIssuer issuer, LoadedMultiverseWorld world, String[] flags) {
|
||||
super.onGameruleListCommand(issuer, world, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
import co.aikar.commands.InvalidCommandArgument;
|
||||
import co.aikar.commands.MessageType;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.display.ContentDisplay;
|
||||
import org.mvplugins.multiverse.core.display.filters.ContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.filters.RegexContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.handlers.PagedSendHandler;
|
||||
import org.mvplugins.multiverse.core.display.parsers.MapContentProvider;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
|
||||
/**
|
||||
* List all gamerules in your current or specified world.
|
||||
*/
|
||||
@Service
|
||||
@CommandAlias("mv")
|
||||
class GamerulesCommand extends MultiverseCommand {
|
||||
|
||||
private final CommandValueFlag<Integer> PAGE_FLAG = flag(CommandValueFlag
|
||||
.builder("--page", Integer.class)
|
||||
.addAlias("-p")
|
||||
.context(value -> {
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new InvalidCommandArgument("Invalid page number: " + value);
|
||||
}
|
||||
})
|
||||
.build());
|
||||
|
||||
private final CommandValueFlag<ContentFilter> FILTER_FLAG = flag(CommandValueFlag
|
||||
.builder("--filter", ContentFilter.class)
|
||||
.addAlias("-f")
|
||||
.context(value -> {
|
||||
try {
|
||||
return RegexContentFilter.fromString(value);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new InvalidCommandArgument("Invalid filter: " + value);
|
||||
}
|
||||
})
|
||||
.build());
|
||||
|
||||
@Inject
|
||||
GamerulesCommand(@NotNull MVCommandManager commandManager) {
|
||||
super(commandManager);
|
||||
}
|
||||
|
||||
@Subcommand("gamerules|rules")
|
||||
@CommandPermission("multiverse.core.gamerule.list")
|
||||
@CommandCompletion("@mvworlds|@flags:groupName=mvgamerulescommand @flags:groupName=mvgamerulescommand")
|
||||
@Syntax("[world] [--page <page>] [--filter <filter>]")
|
||||
@Description("{@@mv-core.gamerules.description}")
|
||||
void onGamerulesCommand(
|
||||
@NotNull MVCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerAware")
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.gamerules.description.world}")
|
||||
LoadedMultiverseWorld world,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--page <page>] [--filter <filter>]")
|
||||
@Description("{@@mv-core.gamerules.description.page}")
|
||||
String[] flags) {
|
||||
ParsedCommandFlags parsedFlags = parseFlags(flags);
|
||||
|
||||
ContentDisplay.create()
|
||||
.addContent(MapContentProvider.forContent(getGameRuleMap(world.getBukkitWorld().getOrNull())) // TODO: Handle null
|
||||
.withKeyColor(ChatColor.AQUA)
|
||||
.withValueColor(ChatColor.WHITE))
|
||||
.withSendHandler(PagedSendHandler.create()
|
||||
.withHeader(this.getTitle(issuer, world.getBukkitWorld().getOrNull()))
|
||||
.doPagination(true)
|
||||
.withTargetPage(parsedFlags.flagValue(PAGE_FLAG, 1))
|
||||
.withFilter(parsedFlags.flagValue(FILTER_FLAG, DefaultContentFilter.get())))
|
||||
.send(issuer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the gamerules and their values for a given world.
|
||||
*
|
||||
* @param world The world to find gamerules for.
|
||||
* @return A map of the gamerules and their values
|
||||
*/
|
||||
private Map<String, String> getGameRuleMap(World world) {
|
||||
Map<String, String> gameRuleMap = new HashMap<>();
|
||||
|
||||
for (GameRule<?> gamerule : GameRule.values()) {
|
||||
Object gameruleValue = world.getGameRuleValue(gamerule);
|
||||
if (gameruleValue == null) {
|
||||
gameRuleMap.put(gamerule.getName(), "null");
|
||||
continue;
|
||||
}
|
||||
gameRuleMap.put(gamerule.getName(), gameruleValue.toString());
|
||||
}
|
||||
return gameRuleMap;
|
||||
}
|
||||
|
||||
private String getTitle(CommandIssuer issuer, World world) {
|
||||
return this.commandManager.formatMessage(
|
||||
issuer,
|
||||
MessageType.INFO,
|
||||
MVCorei18n.GAMERULES_TITLE,
|
||||
"{world}", world.getName());
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.PageFilterFlags;
|
||||
import org.mvplugins.multiverse.core.display.ContentDisplay;
|
||||
import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.handlers.PagedSendHandler;
|
||||
import org.mvplugins.multiverse.core.display.parsers.ListContentProvider;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.utils.StringFormatter;
|
||||
import org.mvplugins.multiverse.core.world.generators.GeneratorPlugin;
|
||||
import org.mvplugins.multiverse.core.world.generators.GeneratorProvider;
|
||||
|
||||
/**
|
||||
* List all gamerules in your current or specified world.
|
||||
*/
|
||||
@Service
|
||||
class GeneratorsCommand extends CoreCommand {
|
||||
|
||||
private final GeneratorProvider generatorProvider;
|
||||
private final PageFilterFlags flags;
|
||||
|
||||
@Inject
|
||||
GeneratorsCommand(@NotNull GeneratorProvider generatorProvider, @NotNull PageFilterFlags flags) {
|
||||
this.generatorProvider = generatorProvider;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Subcommand("generators list")
|
||||
@CommandPermission("multiverse.core.generator")
|
||||
@CommandCompletion("@flags:groupName=" + PageFilterFlags.NAME)
|
||||
@Syntax("[--page <page>] [--filter <filter>]")
|
||||
@Description("{@@mv-core.generators.description}")
|
||||
void onGeneratorsListCommand(
|
||||
@NotNull MVCommandIssuer issuer,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--page <page>] [--filter <filter>]")
|
||||
@Description("{@@mv-core.generators.description.flags}")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
|
||||
// Get the generators loaded using the command suggestions
|
||||
List<String> generators = (List<String>) generatorProvider.suggestGeneratorString("");
|
||||
|
||||
// Tell the user if we cannot find any generator plugins, then abort
|
||||
if (generators.isEmpty()) {
|
||||
issuer.sendMessage(MVCorei18n.GENERATORS_EMPTY);
|
||||
return;
|
||||
}
|
||||
|
||||
ContentDisplay.create()
|
||||
.addContent(ListContentProvider.forContent(generators))
|
||||
.withSendHandler(PagedSendHandler.create()
|
||||
.withHeader("%s====[ Multiverse Generator List ]====", ChatColor.AQUA)
|
||||
.doPagination(true)
|
||||
.withTargetPage(parsedFlags.flagValue(flags.page, 1))
|
||||
.withFilter(parsedFlags.flagValue(flags.filter, DefaultContentFilter.get())))
|
||||
.send(issuer);
|
||||
}
|
||||
|
||||
@Subcommand("generators info")
|
||||
@CommandPermission("multiverse.core.generator")
|
||||
@CommandCompletion("@generatorplugins")
|
||||
@Syntax("<generator>")
|
||||
void onGeneratorsInfoCommand(
|
||||
@NotNull MVCommandIssuer issuer,
|
||||
|
||||
@Syntax("<generator>")
|
||||
GeneratorPlugin generatorPlugin
|
||||
) {
|
||||
issuer.sendMessage(ChatColor.RESET + "Generator Plugin: " + generatorPlugin.getPluginName());
|
||||
issuer.sendMessage(ChatColor.RESET + "Example usages: ");
|
||||
issuer.sendMessage(ChatColor.RESET + StringFormatter.join(generatorPlugin.getExampleUsages(), "\n"));
|
||||
issuer.sendMessage(ChatColor.RESET + "Link to more info: " + generatorPlugin.getInfoLink());
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends GeneratorsCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull GeneratorProvider generatorProvider, @NotNull PageFilterFlags flags) {
|
||||
super(generatorProvider, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvgenerators|mvgens")
|
||||
void onGeneratorsListCommand(@NotNull MVCommandIssuer issuer, String[] flags) {
|
||||
super.onGeneratorsListCommand(issuer, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,37 +14,49 @@ import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.FlagBuilder;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.generators.GeneratorProvider;
|
||||
import org.mvplugins.multiverse.core.world.options.ImportWorldOptions;
|
||||
|
||||
@Service
|
||||
class ImportCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class ImportCommand extends MultiverseCommand {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
private final ImportCommand.Flags flags;
|
||||
|
||||
private GeneratorProvider generatorProvider;
|
||||
private final CommandValueFlag<String> GENERATOR_FLAG = flag(CommandValueFlag
|
||||
.builder("--generator", String.class)
|
||||
.addAlias("-g")
|
||||
.completion(input -> generatorProvider.suggestGeneratorString(input))
|
||||
.build());
|
||||
|
||||
private final CommandFlag NO_ADJUST_SPAWN_FLAG = flag(CommandFlag.builder("--no-adjust-spawn")
|
||||
.addAlias("-n")
|
||||
.build());
|
||||
|
||||
@Inject
|
||||
ImportCommand(@NotNull WorldManager worldManager, @NotNull Flags flags) {
|
||||
ImportCommand(
|
||||
@NotNull MVCommandManager commandManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull GeneratorProvider generatorProvider) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
this.flags = flags;
|
||||
this.generatorProvider = generatorProvider;
|
||||
}
|
||||
|
||||
@Subcommand("import")
|
||||
@CommandPermission("multiverse.core.import")
|
||||
@CommandCompletion("@mvworlds:scope=potential @environments @flags:groupName=" + Flags.NAME)
|
||||
@Syntax("<name> <environment> [--generator <generator[:id]> --adjust-spawn --biome <biome>]")
|
||||
@Description("{@@mv-core.import.description}")
|
||||
@CommandCompletion("@mvworlds:scope=potential @flags:groupName=mvimportcommand")
|
||||
@Syntax("<name> <env> --generator [generator[:id]] --adjust-spawn")
|
||||
@Description("{@@mv-core.import.description")
|
||||
void onImportCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@@ -58,71 +70,23 @@ class ImportCommand extends CoreCommand {
|
||||
World.Environment environment,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--generator <generator[:id]> --adjust-spawn --biome <biome>]")
|
||||
@Syntax("--generator [generator[:id]] --adjust-spawn")
|
||||
@Description("{@@mv-core.import.other.description}")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
String[] flags) {
|
||||
ParsedCommandFlags parsedFlags = parseFlags(flags);
|
||||
|
||||
issuer.sendInfo(MVCorei18n.IMPORT_IMPORTING, Replace.WORLD.with(worldName));
|
||||
issuer.sendInfo(MVCorei18n.IMPORT_IMPORTING, "{world}", worldName);
|
||||
worldManager.importWorld(ImportWorldOptions.worldName(worldName)
|
||||
.biome(parsedFlags.flagValue(flags.biome, ""))
|
||||
.environment(environment)
|
||||
.generator(parsedFlags.flagValue(flags.generator, String.class))
|
||||
.useSpawnAdjust(!parsedFlags.hasFlag(flags.noAdjustSpawn))
|
||||
.doFolderCheck(!parsedFlags.hasFlag(flags.skipFolderCheck)))
|
||||
.environment(environment)
|
||||
.generator(parsedFlags.flagValue(GENERATOR_FLAG, String.class))
|
||||
.useSpawnAdjust(!parsedFlags.hasFlag(NO_ADJUST_SPAWN_FLAG)))
|
||||
.onSuccess(newWorld -> {
|
||||
Logging.fine("World import success: " + newWorld);
|
||||
issuer.sendInfo(MVCorei18n.IMPORT_SUCCESS, Replace.WORLD.with(newWorld.getName()));
|
||||
issuer.sendInfo(MVCorei18n.IMPORT_SUCCESS, "{world}", newWorld.getName());
|
||||
})
|
||||
.onFailure(failure -> {
|
||||
Logging.fine("World import failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class Flags extends FlagBuilder {
|
||||
|
||||
private static final String NAME = "mvimport";
|
||||
|
||||
private GeneratorProvider generatorProvider;
|
||||
|
||||
@Inject
|
||||
private Flags(@NotNull CommandFlagsManager flagsManager, @NotNull GeneratorProvider generatorProvider) {
|
||||
super(NAME, flagsManager);
|
||||
this.generatorProvider = generatorProvider;
|
||||
}
|
||||
|
||||
private final CommandValueFlag<String> generator = flag(CommandValueFlag
|
||||
.builder("--generator", String.class)
|
||||
.addAlias("-g")
|
||||
.completion(input -> generatorProvider.suggestGeneratorString(input))
|
||||
.build());
|
||||
|
||||
private final CommandFlag noAdjustSpawn = flag(CommandFlag.builder("--no-adjust-spawn")
|
||||
.addAlias("-n")
|
||||
.build());
|
||||
|
||||
private final CommandValueFlag<String> biome = flag(CommandValueFlag.builder("--biome", String.class)
|
||||
.addAlias("-b")
|
||||
.build());
|
||||
|
||||
private final CommandFlag skipFolderCheck = flag(CommandFlag.builder("--skip-folder-check")
|
||||
.addAlias("-f")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends ImportCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull WorldManager worldManager, @NotNull Flags flags) {
|
||||
super(worldManager, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvimport|mvim")
|
||||
void onImportCommand(MVCommandIssuer issuer, String worldName, World.Environment environment, String[] flags) {
|
||||
super.onImportCommand(issuer, worldName, environment, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.WorldType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.PageFilterFlags;
|
||||
import org.mvplugins.multiverse.core.display.ContentDisplay;
|
||||
import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.handlers.PagedSendHandler;
|
||||
import org.mvplugins.multiverse.core.display.parsers.MapContentProvider;
|
||||
import org.mvplugins.multiverse.core.economy.MVEconomist;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
import org.mvplugins.multiverse.core.teleportation.LocationManipulation;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
|
||||
import static org.mvplugins.multiverse.core.locale.message.MessageReplacement.replace;
|
||||
|
||||
@Service
|
||||
class InfoCommand extends CoreCommand {
|
||||
|
||||
private final LocationManipulation locationManipulation;
|
||||
private final MVEconomist economist;
|
||||
private final PageFilterFlags flags;
|
||||
|
||||
@Inject
|
||||
InfoCommand(
|
||||
@NotNull LocationManipulation locationManipulation,
|
||||
@NotNull MVEconomist economist,
|
||||
@NotNull PageFilterFlags flags
|
||||
) {
|
||||
this.locationManipulation = locationManipulation;
|
||||
this.economist = economist;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
// TODO: support info for unloaded worlds
|
||||
@Subcommand("info")
|
||||
@CommandPermission("multiverse.core.info")
|
||||
@CommandCompletion("@mvworlds:scope=both|@flags:resolveUntil=arg1,groupName=" + PageFilterFlags.NAME + " @flags:groupName=" + PageFilterFlags.NAME)
|
||||
@Syntax("[world] [--page <page>] [--filter <filter>]")
|
||||
@Description("{@@mv-core.info.description}")
|
||||
public void onInfoCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerAware,maxArgForAware=0")
|
||||
@Syntax("[world]")
|
||||
@Description("{@@mv-core.info.description.world}")
|
||||
LoadedMultiverseWorld world,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--page <page>] [--filter <filter>]")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
|
||||
ContentDisplay.create()
|
||||
.addContent(MapContentProvider.forContent(getInfo(world))
|
||||
.withKeyColor(ChatColor.AQUA)
|
||||
.withValueColor(ChatColor.WHITE))
|
||||
.withSendHandler(PagedSendHandler.create()
|
||||
.withHeader(Message.of(MVCorei18n.INFO_HEADER, replace("{world}").with(world.getName())))
|
||||
.noContentMessage(Message.of(MVCorei18n.INFO_NOCONTENT))
|
||||
.doPagination(true)
|
||||
.withTargetPage(parsedFlags.flagValue(flags.page, 1))
|
||||
.withFilter(parsedFlags.flagValue(flags.filter, DefaultContentFilter.get())))
|
||||
.send(issuer);
|
||||
}
|
||||
|
||||
private Map<String, String> getInfo(LoadedMultiverseWorld world) {
|
||||
Map<String, String> outMap = new LinkedHashMap<>();
|
||||
|
||||
outMap.put("World Name", world.getName());
|
||||
outMap.put("World Alias", world.getAlias());
|
||||
outMap.put("World UID", world.getUID().toString());
|
||||
outMap.put("Game Mode", world.getGameMode().toString());
|
||||
outMap.put("Difficulty", world.getDifficulty().toString());
|
||||
|
||||
outMap.put("Spawn Location", locationManipulation.strCoords(world.getSpawnLocation()));
|
||||
outMap.put("Respawn World", world.getRespawnWorldName());
|
||||
outMap.put("Bed Respawn", String.valueOf(world.getBedRespawn()));
|
||||
outMap.put("Anchor Respawn", String.valueOf(world.getAnchorRespawn()));
|
||||
|
||||
outMap.put("Seed", String.valueOf(world.getSeed()));
|
||||
outMap.put("Environment", String.valueOf(world.getEnvironment()));
|
||||
outMap.put("World Type", world.getWorldType().map(WorldType::getName).getOrNull());
|
||||
outMap.put("Biome", world.getBiome());
|
||||
outMap.put("Generator", world.getGenerator());
|
||||
outMap.put("Generate Structures", world.canGenerateStructures().map(String::valueOf).getOrNull());
|
||||
|
||||
outMap.put("Auto Load", String.valueOf(world.isAutoLoad()));
|
||||
outMap.put("Keep Spawn In Memory", String.valueOf(world.isKeepSpawnInMemory()));
|
||||
|
||||
getEntryFeeInfo(outMap, world);
|
||||
outMap.put("World Scale", String.valueOf(world.getScale()));
|
||||
outMap.put("Weather Enabled", String.valueOf(world.isAllowWeather()));
|
||||
outMap.put("Allow Flight", String.valueOf(world.isAllowFlight()));
|
||||
outMap.put("Hunger Depletes", String.valueOf(world.isHunger()));
|
||||
outMap.put("Keep Spawn In Memory", String.valueOf(world.isKeepSpawnInMemory()));
|
||||
outMap.put("PVP Enabled", String.valueOf(world.getPvp()));
|
||||
outMap.put("Portal Form", String.valueOf(world.getPortalForm()));
|
||||
outMap.put("Player Limit", String.valueOf(world.getPlayerLimit()));
|
||||
// getAnimalSpawningInfo(outMap, world);
|
||||
// getMonsterSpawningInfo(outMap, world);
|
||||
outMap.put("World Blacklist", String.join(", ", world.getWorldBlacklist()));
|
||||
|
||||
return outMap;
|
||||
}
|
||||
|
||||
private void getEntryFeeInfo(Map<String, String> outMap, MultiverseWorld world) {
|
||||
double price = world.getPrice();
|
||||
if (price == 0) {
|
||||
outMap.put("Entry Fee", "FREE!");
|
||||
} else if (price > 0) {
|
||||
outMap.put("Entry Fee", economist.formatPrice(price, world.getCurrency()));
|
||||
} else if (price < 0) {
|
||||
outMap.put("Entry Reward", economist.formatPrice(-price, world.getCurrency()));
|
||||
}
|
||||
}
|
||||
|
||||
// private void getAnimalSpawningInfo(Map<String, String> outMap, MultiverseWorld world) {
|
||||
// if (world.isSpawningAnimals()) {
|
||||
// outMap.put("Spawning Animals", "ALL");
|
||||
// } else {
|
||||
// if (!world.getSpawningAnimalsExceptions().isEmpty()) {
|
||||
// outMap.put("Spawning Animals", world.getSpawningAnimalsExceptions().toString());
|
||||
// } else {
|
||||
// outMap.put("Spawning Animals", "NONE");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void getMonsterSpawningInfo(Map<String, String> outMap, MultiverseWorld world) {
|
||||
// if (world.isSpawningMonsters()) {
|
||||
// outMap.put("Spawning Monsters", "ALL");
|
||||
// } else {
|
||||
// if (!world.getSpawningMonstersExceptions().isEmpty()) {
|
||||
// outMap.put("Spawning Monsters", world.getSpawningMonstersExceptions().toString());
|
||||
// } else {
|
||||
// outMap.put("Spawning Monsters", "NONE");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends InfoCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(
|
||||
@NotNull LocationManipulation locationManipulation,
|
||||
@NotNull MVEconomist economist,
|
||||
@NotNull PageFilterFlags flags
|
||||
) {
|
||||
super(locationManipulation, economist, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvinfo|mvi")
|
||||
public void onInfoCommand(MVCommandIssuer issuer, LoadedMultiverseWorld world, String[] flags) {
|
||||
super.onInfoCommand(issuer, world, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package org.mvplugins.multiverse.core.commands;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import co.aikar.commands.InvalidCommandArgument;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
@@ -15,107 +16,110 @@ import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.PageFilterFlags;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.display.ContentDisplay;
|
||||
import org.mvplugins.multiverse.core.display.filters.ContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.filters.RegexContentFilter;
|
||||
import org.mvplugins.multiverse.core.display.handlers.PagedSendHandler;
|
||||
import org.mvplugins.multiverse.core.display.parsers.ListContentProvider;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.entrycheck.WorldEntryChecker;
|
||||
import org.mvplugins.multiverse.core.world.entrycheck.WorldEntryCheckerProvider;
|
||||
|
||||
@Service
|
||||
class ListCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class ListCommand extends MultiverseCommand {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
private final WorldEntryCheckerProvider worldEntryCheckerProvider;
|
||||
private final ListCommand.Flags flags;
|
||||
|
||||
private final CommandValueFlag<Integer> PAGE_FLAG = flag(CommandValueFlag
|
||||
.builder("--page", Integer.class)
|
||||
.addAlias("-p")
|
||||
.context(value -> {
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new InvalidCommandArgument("Invalid page number: " + value);
|
||||
}
|
||||
})
|
||||
.build());
|
||||
|
||||
private final CommandValueFlag<ContentFilter> FILTER_FLAG = flag(CommandValueFlag
|
||||
.builder("--filter", ContentFilter.class)
|
||||
.addAlias("-f")
|
||||
.context(value -> {
|
||||
try {
|
||||
return RegexContentFilter.fromString(value);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new InvalidCommandArgument("Invalid filter: " + value);
|
||||
}
|
||||
})
|
||||
.build());
|
||||
|
||||
@Inject
|
||||
ListCommand(
|
||||
@NotNull MVCommandManager commandManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull WorldEntryCheckerProvider worldEntryCheckerProvider,
|
||||
@NotNull Flags flags
|
||||
) {
|
||||
@NotNull WorldEntryCheckerProvider worldEntryCheckerProvider) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
this.worldEntryCheckerProvider = worldEntryCheckerProvider;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Subcommand("list")
|
||||
@CommandPermission("multiverse.core.list.worlds")
|
||||
@CommandCompletion("@flags:groupName=" + Flags.NAME)
|
||||
@Syntax("--filter [filter] --page [page] --raw")
|
||||
@Description("{{@mv-core.list.description}}")
|
||||
@CommandCompletion("@flags:groupName=mvlistcommand")
|
||||
@Syntax("--filter [filter] --page [page]")
|
||||
@Description("Displays a listing of all worlds that you can enter.")
|
||||
public void onListCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Syntax("[--filter <filter>] [--page <page>]")
|
||||
@Description("Filters the list of worlds by the given regex and displays the given page.")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
String[] flags) {
|
||||
ParsedCommandFlags parsedFlags = parseFlags(flags);
|
||||
ContentDisplay.create()
|
||||
.addContent(ListContentProvider.forContent(getListContents(issuer, parsedFlags.hasFlag(flags.raw))))
|
||||
.addContent(ListContentProvider.forContent(getListContents(issuer)))
|
||||
.withSendHandler(PagedSendHandler.create()
|
||||
.noContentMessage(Message.of(MVCorei18n.LIST_NOCONTENT))
|
||||
.withHeader(Message.of(MVCorei18n.LIST_HEADER))
|
||||
.withTargetPage(parsedFlags.flagValue(flags.page, 1))
|
||||
.withFilter(parsedFlags.flagValue(flags.filter, DefaultContentFilter.get())))
|
||||
.withHeader("%s====[ Multiverse World List ]====", ChatColor.GOLD)
|
||||
.withTargetPage(parsedFlags.flagValue(PAGE_FLAG, 1))
|
||||
.withFilter(parsedFlags.flagValue(FILTER_FLAG, DefaultContentFilter.get())))
|
||||
.send(issuer);
|
||||
}
|
||||
|
||||
private List<String> getListContents(MVCommandIssuer issuer, boolean useRawNames) {
|
||||
private List<String> getListContents(MVCommandIssuer issuer) {
|
||||
List<String> worldList = new ArrayList<>();
|
||||
WorldEntryChecker worldEntryChecker = worldEntryCheckerProvider.forSender(issuer.getIssuer());
|
||||
|
||||
worldManager.getLoadedWorlds().stream()
|
||||
.filter(world -> worldEntryChecker.canAccessWorld(world).isSuccess())
|
||||
.filter(world -> canSeeWorld(issuer, world))
|
||||
.map(world -> hiddenText(world) + getWorldName(world, useRawNames) + " - "
|
||||
+ parseColouredEnvironment(world.getEnvironment()))
|
||||
.map(world -> hiddenText(world) + world.getAlias() + " - " + parseColouredEnvironment(world.getEnvironment()))
|
||||
.sorted()
|
||||
.forEach(worldList::add);
|
||||
|
||||
worldManager.getUnloadedWorlds().stream()
|
||||
.filter(world -> worldEntryChecker.canAccessWorld(world).isSuccess())
|
||||
.map(world -> ChatColor.GRAY + getWorldName(world, useRawNames) + " - UNLOADED")
|
||||
.map(world -> ChatColor.GRAY + world.getAlias() + " - UNLOADED")
|
||||
.sorted()
|
||||
.forEach(worldList::add);
|
||||
|
||||
return worldList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a world's name or alias.
|
||||
*
|
||||
* @param world The world to retrieve the name of
|
||||
* @param useRawNames True to return the name, false to return the alias
|
||||
* @return The name
|
||||
*/
|
||||
private String getWorldName(MultiverseWorld world, boolean useRawNames) {
|
||||
if (useRawNames) {
|
||||
return world.getName();
|
||||
}
|
||||
|
||||
return world.getAliasOrName();
|
||||
}
|
||||
|
||||
private boolean canSeeWorld(MVCommandIssuer issuer, MultiverseWorld world) {
|
||||
private boolean canSeeWorld(MVCommandIssuer issuer, LoadedMultiverseWorld world) {
|
||||
return !world.isHidden()
|
||||
// TODO: Refactor stray permission check
|
||||
|| issuer.hasPermission("multiverse.core.modify");
|
||||
|| issuer.hasPermission("multiverse.core.modify"); // TODO: Refactor stray permission check
|
||||
}
|
||||
|
||||
private String hiddenText(MultiverseWorld world) {
|
||||
private String hiddenText(LoadedMultiverseWorld world) {
|
||||
return (world.isHidden()) ? String.format("%s[H] ", ChatColor.GRAY) : "";
|
||||
}
|
||||
|
||||
@@ -128,37 +132,4 @@ class ListCommand extends CoreCommand {
|
||||
};
|
||||
return color + env.toString();
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class Flags extends PageFilterFlags {
|
||||
|
||||
private static final String NAME = "mvlist";
|
||||
|
||||
@Inject
|
||||
private Flags(@NotNull CommandFlagsManager flagsManager) {
|
||||
super(NAME, flagsManager);
|
||||
}
|
||||
|
||||
private final CommandFlag raw = flag(CommandFlag.builder("--raw")
|
||||
.addAlias("-r")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends ListCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull WorldEntryCheckerProvider worldEntryCheckerProvider,
|
||||
@NotNull Flags flags
|
||||
) {
|
||||
super(worldManager, worldEntryCheckerProvider, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvlist|mvl")
|
||||
public void onListCommand(MVCommandIssuer issuer, String[] flags) {
|
||||
super.onListCommand(issuer, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,9 @@ package org.mvplugins.multiverse.core.commands;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Conditions;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Single;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
@@ -12,28 +13,22 @@ import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.RemovePlayerFlags;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.options.LoadWorldOptions;
|
||||
|
||||
@Service
|
||||
class LoadCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class LoadCommand extends MultiverseCommand {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
private final LoadCommand.Flags flags;
|
||||
|
||||
@Inject
|
||||
LoadCommand(@NotNull WorldManager worldManager, @NotNull Flags flags) {
|
||||
LoadCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Subcommand("load")
|
||||
@@ -44,54 +39,19 @@ class LoadCommand extends CoreCommand {
|
||||
void onLoadCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Single
|
||||
@Conditions("worldname:scope=unloaded")
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.load.world.description}")
|
||||
MultiverseWorld world,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--remove-players]")
|
||||
@Description("")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
|
||||
issuer.sendInfo(MVCorei18n.LOAD_LOADING, Replace.WORLD.with(world.getName()));
|
||||
worldManager.loadWorld(LoadWorldOptions.world(world)
|
||||
.doFolderCheck(!parsedFlags.hasFlag(flags.skipFolderCheck)))
|
||||
String worldName) {
|
||||
issuer.sendInfo(MVCorei18n.LOAD_LOADING, "{world}", worldName);
|
||||
worldManager.loadWorld(worldName)
|
||||
.onSuccess(newWorld -> {
|
||||
Logging.fine("World load success: " + newWorld);
|
||||
issuer.sendInfo(MVCorei18n.LOAD_SUCCESS, Replace.WORLD.with(newWorld.getName()));
|
||||
issuer.sendInfo(MVCorei18n.LOAD_SUCCESS, "{world}", newWorld.getName());
|
||||
}).onFailure(failure -> {
|
||||
Logging.fine("World load failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class Flags extends RemovePlayerFlags {
|
||||
|
||||
private static final String NAME = "mvunload";
|
||||
|
||||
@Inject
|
||||
private Flags(@NotNull CommandFlagsManager flagsManager) {
|
||||
super(NAME, flagsManager);
|
||||
}
|
||||
|
||||
private final CommandFlag skipFolderCheck = flag(CommandFlag.builder("--skip-folder-check")
|
||||
.addAlias("-f")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends LoadCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull WorldManager worldManager, @NotNull Flags flags) {
|
||||
super(worldManager, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvload")
|
||||
void onLoadCommand(MVCommandIssuer issuer, MultiverseWorld world, String[] flagArray) {
|
||||
super.onLoadCommand(issuer, world, flagArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,131 +5,72 @@ import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Single;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jvnet.hk2.annotations.Optional;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.context.issueraware.MultiverseWorldValue;
|
||||
import org.mvplugins.multiverse.core.config.handle.PropertyModifyAction;
|
||||
import org.mvplugins.multiverse.core.config.handle.StringPropertyHandle;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.configuration.handle.ConfigModifyType;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.mvplugins.multiverse.core.locale.message.MessageReplacement.*;
|
||||
import static org.mvplugins.multiverse.core.locale.message.MessageReplacement.replace;
|
||||
|
||||
@Service
|
||||
class ModifyCommand extends CoreCommand {
|
||||
|
||||
private static final Map<String, String> REMOVED_PROPERTIES = Map.of(
|
||||
"animals", "/mv entity-spawn-config modify [world] animal set spawn <true|false>",
|
||||
"monsters", "/mv entity-spawn-config modify [world] monster set spawn <true|false>"
|
||||
);
|
||||
@CommandAlias("mv")
|
||||
class ModifyCommand extends MultiverseCommand {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
ModifyCommand(WorldManager worldManager) {
|
||||
ModifyCommand(@NotNull MVCommandManager commandManager, WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
|
||||
/* /mv modify [world] <set|add|remove|reset> <property> <value> */
|
||||
@Subcommand("modify")
|
||||
@CommandPermission("multiverse.core.modify")
|
||||
@CommandCompletion("@mvworlds:scope=both|@propsmodifyaction:byIssuerForArg=arg1 " +
|
||||
"@propsmodifyaction:notByIssuerForArg=arg1|@mvworldpropsname:byIssuerForArg=arg1 " +
|
||||
"@mvworldpropsname:notByIssuerForArg=arg1|@mvworldpropsvalue:byIssuerForArg=arg1 " +
|
||||
"@mvworldpropsvalue:notByIssuerForArg=arg1")
|
||||
@Syntax("[world] <set|add|remove|reset> <property> [value]")
|
||||
@Description("{@@mv-core.modify.description}")
|
||||
void onModifyCommand(// SUPPRESS CHECKSTYLE: ParameterNumber
|
||||
@CommandCompletion("@mvworlds:scope=both @configmodifytype @mvworldpropsname @mvworldpropsvalue")
|
||||
@Syntax("[world] <set|add|remove|reset> <property> <value>")
|
||||
@Description("")
|
||||
void onModifyCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerAware,maxArgForAware=3")
|
||||
@Flags("resolve=issuerAware")
|
||||
@Syntax("[world]")
|
||||
@Description("{@@mv-core.modify.world.description}")
|
||||
@NotNull MultiverseWorldValue worldValue,
|
||||
@Description("")
|
||||
MultiverseWorld world,
|
||||
|
||||
@Syntax("<set|add|remove|reset>")
|
||||
@Description("")
|
||||
@NotNull PropertyModifyAction action,
|
||||
ConfigModifyType configModifyType,
|
||||
|
||||
@Syntax("<property>")
|
||||
@Description("{@@mv-core.modify.property.description}")
|
||||
@NotNull String propertyName,
|
||||
@Description("")
|
||||
String propertyName,
|
||||
|
||||
@Optional
|
||||
@Single
|
||||
@Syntax("[value]")
|
||||
@Description("{@@mv-core.modify.value.description}")
|
||||
@Nullable String propertyValue) {
|
||||
if (REMOVED_PROPERTIES.containsKey(propertyName)) {
|
||||
issuer.sendMessage(MVCorei18n.MODIFY_PROPERTYREMOVED,
|
||||
replace("{property}").with(propertyName),
|
||||
replace("{replacement}").with(REMOVED_PROPERTIES.get(propertyName)));
|
||||
return;
|
||||
}
|
||||
@Description("")
|
||||
String propertyValue) {
|
||||
Logging.fine("ModifyCommand.onModifyCommand: world=%s, configModifyType=%s, propertyName=%s, propertyValue=%s",
|
||||
world, configModifyType, propertyName, propertyValue);
|
||||
|
||||
MultiverseWorld world = worldValue.value();
|
||||
|
||||
if (action.isRequireValue() && propertyValue == null) {
|
||||
issuer.sendMessage(MVCorei18n.MODIFY_SPECIFYVALUE,
|
||||
replace("{action}").with(action.name().toLowerCase()),
|
||||
replace("{property}").with(propertyName));
|
||||
return;
|
||||
} else if (!action.isRequireValue() && propertyValue != null) {
|
||||
issuer.sendMessage(MVCorei18n.MODIFY_CANNOTHAVEVALUE,
|
||||
replace("{action}").with(action.name().toLowerCase()),
|
||||
replace("{property}").with(propertyName));
|
||||
return;
|
||||
}
|
||||
|
||||
StringPropertyHandle worldPropertyHandle = world.getStringPropertyHandle();
|
||||
worldPropertyHandle.modifyPropertyString(issuer.getIssuer(), propertyName, propertyValue, action)
|
||||
.andThenTry(worldManager::saveWorldsConfig)
|
||||
.onSuccess(ignore -> issuer.sendMessage(MVCorei18n.MODIFY_SUCCESS,
|
||||
replace("{action}").with(action.name().toLowerCase()),
|
||||
replace("{property}").with(propertyName),
|
||||
Replace.VALUE.with(worldPropertyHandle.getProperty(propertyName).getOrNull()),
|
||||
Replace.WORLD.with(world.getName())))
|
||||
.onFailure(exception -> {
|
||||
if (propertyValue == null) {
|
||||
issuer.sendMessage(MVCorei18n.MODIFY_FAILURE_NOVALUE,
|
||||
replace("{action}").with(action.name().toLowerCase()),
|
||||
replace("{property}").with(propertyName),
|
||||
Replace.WORLD.with(world.getName()),
|
||||
Replace.ERROR.with(exception.getMessage()));
|
||||
} else {
|
||||
issuer.sendMessage(MVCorei18n.MODIFY_FAILURE,
|
||||
replace("{action}").with(action.name().toLowerCase()),
|
||||
replace("{property}").with(propertyName),
|
||||
Replace.VALUE.with(propertyValue),
|
||||
Replace.WORLD.with(world.getName()),
|
||||
Replace.ERROR.with(exception.getMessage()));
|
||||
}
|
||||
world.modifyProperty(configModifyType, propertyName, propertyValue).onSuccess(ignore -> {
|
||||
issuer.sendMessage("Property " + propertyName + " set to " + world.getProperty(propertyName).getOrNull()
|
||||
+ " for world " + world.getName() + ".");
|
||||
worldManager.saveWorldsConfig();
|
||||
}).onFailure(exception -> {
|
||||
issuer.sendMessage("Failed to " + configModifyType.name().toLowerCase() + " property " + propertyName
|
||||
+ " to " + propertyValue + " for world " + world.getName() + ".");
|
||||
issuer.sendMessage(exception.getMessage());
|
||||
});
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends ModifyCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(WorldManager worldManager) {
|
||||
super(worldManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvmodify|mvm")
|
||||
void onModifyCommand(MVCommandIssuer issuer, @NotNull MultiverseWorldValue world, @NotNull PropertyModifyAction action, @NotNull String propertyName, @Nullable String propertyValue) {
|
||||
super.onModifyCommand(issuer, world, action, propertyName, propertyValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.entity.SpawnCategory;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.utils.StringFormatter;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.entity.EntityPurger;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
final class PurgeAllEntitiesCommand extends CoreCommand {
|
||||
|
||||
private final EntityPurger entityPurger;
|
||||
|
||||
@Inject
|
||||
PurgeAllEntitiesCommand(EntityPurger entityPurger) {
|
||||
this.entityPurger = entityPurger;
|
||||
}
|
||||
|
||||
@Subcommand("purge-all-entities")
|
||||
@CommandPermission("multiverse.core.purgeall")
|
||||
@CommandCompletion("@mvworlds:scope=loaded|@spawncategories:multiple,resolveUntil=arg1 @spawncategories:multiple")
|
||||
@Syntax("[world] [spawn-categories]")
|
||||
void onPurgeAllEntitiesCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerAware,maxArgForAware=1")
|
||||
@Syntax("[world]")
|
||||
LoadedMultiverseWorld world,
|
||||
|
||||
@Optional
|
||||
@Syntax("[spawn-categories]")
|
||||
SpawnCategory[] spawnCategories
|
||||
) {
|
||||
if (spawnCategories == null || spawnCategories.length == 0) {
|
||||
int purgeCount = entityPurger.purgeAllEntities(world);
|
||||
issuer.sendMessage("Successfully purged " + purgeCount + " entities in world " + world.getName() + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
int purgeCount = entityPurger.purgeEntities(world, spawnCategories);
|
||||
issuer.sendMessage("Successfully purged " + purgeCount + " entities in world " + world.getName() +
|
||||
" for spawn categories " + StringFormatter.join(List.of(spawnCategories), ", ") + ".");
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.entity.EntityPurger;
|
||||
|
||||
@Service
|
||||
final class PurgeEntitiesCommand extends CoreCommand {
|
||||
|
||||
private final EntityPurger entityPurger;
|
||||
|
||||
@Inject
|
||||
PurgeEntitiesCommand(EntityPurger entityPurger) {
|
||||
this.entityPurger = entityPurger;
|
||||
}
|
||||
|
||||
@Subcommand("purge-entities")
|
||||
@CommandPermission("multiverse.core.purge")
|
||||
@CommandCompletion("@mvworlds:scope=loaded")
|
||||
@Syntax("[world]")
|
||||
void onPurgeEntityCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerAware,maxArgForAware=0")
|
||||
@Syntax("[world]")
|
||||
LoadedMultiverseWorld world
|
||||
) {
|
||||
int purgeCount = entityPurger.purgeEntities(world);
|
||||
issuer.sendMessage("Successfully purged " + purgeCount + " entities in world " + world.getName() + ".");
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import co.aikar.commands.ACFUtil;
|
||||
import co.aikar.commands.MessageType;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
@@ -13,59 +13,54 @@ import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.RemovePlayerFlags;
|
||||
import org.mvplugins.multiverse.core.command.queue.CommandQueueManager;
|
||||
import org.mvplugins.multiverse.core.command.queue.CommandQueuePayload;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.utils.REPatterns;
|
||||
import org.mvplugins.multiverse.core.utils.WorldTickDeferrer;
|
||||
import org.mvplugins.multiverse.core.utils.result.AsyncAttemptsAggregate;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.CommandValueFlag;
|
||||
import org.mvplugins.multiverse.core.commandtools.flags.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.commandtools.queue.QueuedCommand;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.helpers.PlayerWorldTeleporter;
|
||||
import org.mvplugins.multiverse.core.world.options.RegenWorldOptions;
|
||||
|
||||
@Service
|
||||
class RegenCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class RegenCommand extends MultiverseCommand {
|
||||
|
||||
@NotNull
|
||||
private final CommandQueueManager commandQueueManager;
|
||||
private final WorldManager worldManager;
|
||||
private final PlayerWorldTeleporter playerWorldTeleporter;
|
||||
private final WorldTickDeferrer worldTickDeferrer;
|
||||
private final RegenCommand.Flags flags;
|
||||
|
||||
private final CommandValueFlag<String> SEED_FLAG = flag(CommandValueFlag.builder("--seed", String.class)
|
||||
.addAlias("-s")
|
||||
.completion(input -> Collections.singleton(String.valueOf(new Random().nextLong())))
|
||||
.build());
|
||||
|
||||
private final CommandFlag RESET_WORLD_CONFIG_FLAG = flag(CommandFlag.builder("--reset-world-config")
|
||||
.addAlias("-wc")
|
||||
.build());
|
||||
|
||||
private final CommandFlag RESET_GAMERULES_FLAG = flag(CommandFlag.builder("--reset-gamerules")
|
||||
.addAlias("-gm")
|
||||
.build());
|
||||
|
||||
private final CommandFlag RESET_WORLD_BORDER_FLAG = flag(CommandFlag.builder("--reset-world-border")
|
||||
.addAlias("-wb")
|
||||
.build());
|
||||
|
||||
@Inject
|
||||
RegenCommand(
|
||||
@NotNull CommandQueueManager commandQueueManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull PlayerWorldTeleporter playerWorldTeleporter,
|
||||
@NotNull WorldTickDeferrer worldTickDeferrer,
|
||||
@NotNull Flags flags
|
||||
) {
|
||||
this.commandQueueManager = commandQueueManager;
|
||||
RegenCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
this.playerWorldTeleporter = playerWorldTeleporter;
|
||||
this.worldTickDeferrer = worldTickDeferrer;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Subcommand("regen")
|
||||
@CommandPermission("multiverse.core.regen")
|
||||
@CommandCompletion("@mvworlds:scope=loaded @flags:groupName=" + Flags.NAME)
|
||||
@Syntax("<world> [--seed [seed] --reset-world-config --reset-gamerules --reset-world-border --remove-players]")
|
||||
@CommandCompletion("@mvworlds:scope=loaded @flags:groupName=mvregencommand")
|
||||
@Syntax("<world> --seed [seed] --keep-gamerules")
|
||||
@Description("{@@mv-core.regen.description}")
|
||||
void onRegenCommand(
|
||||
MVCommandIssuer issuer,
|
||||
@@ -75,111 +70,30 @@ class RegenCommand extends CoreCommand {
|
||||
LoadedMultiverseWorld world,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--seed [seed] --reset-world-config --reset-gamerules --reset-world-border --remove-players]")
|
||||
@Syntax("--seed [seed] --reset-gamerules")
|
||||
@Description("{@@mv-core.regen.other.description}")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
String[] flags) {
|
||||
ParsedCommandFlags parsedFlags = parseFlags(flags);
|
||||
|
||||
commandQueueManager.addToQueue(CommandQueuePayload
|
||||
.issuer(issuer)
|
||||
.action(() -> runRegenCommand(issuer, world, parsedFlags))
|
||||
.prompt(Message.of(MVCorei18n.REGEN_PROMPT, "",
|
||||
Replace.WORLD.with(world.getName()))));
|
||||
}
|
||||
|
||||
private void runRegenCommand(MVCommandIssuer issuer, LoadedMultiverseWorld world, ParsedCommandFlags parsedFlags) {
|
||||
issuer.sendInfo(MVCorei18n.REGEN_REGENERATING, Replace.WORLD.with(world.getName()));
|
||||
List<Player> worldPlayers = world.getPlayers().getOrElse(Collections.emptyList());
|
||||
|
||||
var future = parsedFlags.hasFlag(flags.removePlayers)
|
||||
? playerWorldTeleporter.removeFromWorld(world)
|
||||
: AsyncAttemptsAggregate.emptySuccess();
|
||||
|
||||
// todo: using future will hide stacktrace
|
||||
future.onSuccess(() -> worldTickDeferrer
|
||||
.deferWorldTick(() -> doWorldRegening(issuer, world, parsedFlags, worldPlayers)))
|
||||
.onFailure(() -> issuer.sendError("Failed to teleport one or more players out of the world!"));
|
||||
}
|
||||
|
||||
private void doWorldRegening(
|
||||
MVCommandIssuer issuer,
|
||||
LoadedMultiverseWorld world,
|
||||
ParsedCommandFlags parsedFlags,
|
||||
List<Player> worldPlayers) {
|
||||
//todo: Change biome on regen
|
||||
RegenWorldOptions regenWorldOptions = RegenWorldOptions.world(world)
|
||||
.randomSeed(parsedFlags.hasFlag(flags.seed))
|
||||
.seed(parsedFlags.flagValue(flags.seed))
|
||||
.keepWorldConfig(!parsedFlags.hasFlag(flags.resetWorldConfig))
|
||||
.keepGameRule(!parsedFlags.hasFlag(flags.resetGamerules))
|
||||
.keepWorldBorder(!parsedFlags.hasFlag(flags.resetWorldBorder))
|
||||
.keepFiles(parsedFlags.flagValue(flags.keepFiles));
|
||||
|
||||
worldManager.regenWorld(regenWorldOptions).onSuccess(newWorld -> {
|
||||
Logging.fine("World regen success: " + newWorld);
|
||||
issuer.sendInfo(MVCorei18n.REGEN_SUCCESS, Replace.WORLD.with(newWorld.getName()));
|
||||
if (parsedFlags.hasFlag(flags.removePlayers)) {
|
||||
playerWorldTeleporter.teleportPlayersToWorld(worldPlayers, newWorld);
|
||||
}
|
||||
}).onFailure(failure -> {
|
||||
Logging.warning("World regen failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class Flags extends RemovePlayerFlags {
|
||||
|
||||
private static final String NAME = "mvregen";
|
||||
|
||||
@Inject
|
||||
private Flags(@NotNull CommandFlagsManager flagsManager) {
|
||||
super(NAME, flagsManager);
|
||||
}
|
||||
|
||||
private final CommandValueFlag<String> seed = flag(CommandValueFlag.builder("--seed", String.class)
|
||||
.addAlias("-s")
|
||||
.completion(input -> Collections.singleton(String.valueOf(ACFUtil.RANDOM.nextLong())))
|
||||
.optional()
|
||||
.build());
|
||||
|
||||
private final CommandFlag resetWorldConfig = flag(CommandFlag.builder("--reset-world-config")
|
||||
.addAlias("-wc")
|
||||
.build());
|
||||
|
||||
private final CommandFlag resetGamerules = flag(CommandFlag.builder("--reset-gamerules")
|
||||
.addAlias("-gm")
|
||||
.build());
|
||||
|
||||
private final CommandFlag resetWorldBorder = flag(CommandFlag.builder("--reset-world-border")
|
||||
.addAlias("-wb")
|
||||
.build());
|
||||
|
||||
private final CommandValueFlag<List> keepFiles = flag(CommandValueFlag.builder("--keep-files", List.class)
|
||||
.addAlias("-f")
|
||||
.completion(input -> List.of("paper-world.yml"))
|
||||
.defaultValue(Collections.emptyList())
|
||||
.context(input -> List.of(REPatterns.COMMA.split(input)))
|
||||
.build());
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends RegenCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(
|
||||
@NotNull CommandQueueManager commandQueueManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull PlayerWorldTeleporter playerWorldTeleporter,
|
||||
@NotNull WorldTickDeferrer worldTickDeferrer,
|
||||
@NotNull Flags flags
|
||||
) {
|
||||
super(commandQueueManager, worldManager, playerWorldTeleporter, worldTickDeferrer, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvregen")
|
||||
void onRegenCommand(MVCommandIssuer issuer, LoadedMultiverseWorld world, String[] flags) {
|
||||
super.onRegenCommand(issuer, world, flags);
|
||||
}
|
||||
this.commandManager.getCommandQueueManager().addToQueue(new QueuedCommand(
|
||||
issuer.getIssuer(),
|
||||
() -> {
|
||||
issuer.sendInfo(MVCorei18n.REGEN_REGENERATING, "{world}", world.getName());
|
||||
worldManager.regenWorld(RegenWorldOptions.world(world)
|
||||
.randomSeed(parsedFlags.hasFlag(SEED_FLAG))
|
||||
.seed(parsedFlags.flagValue(SEED_FLAG))
|
||||
.keepWorldConfig(!parsedFlags.hasFlag(RESET_WORLD_CONFIG_FLAG))
|
||||
.keepGameRule(!parsedFlags.hasFlag(RESET_GAMERULES_FLAG))
|
||||
.keepWorldBorder(!parsedFlags.hasFlag(RESET_WORLD_BORDER_FLAG))
|
||||
).onSuccess(newWorld -> {
|
||||
Logging.fine("World regen success: " + newWorld);
|
||||
issuer.sendInfo(MVCorei18n.REGEN_SUCCESS, "{world}", newWorld.getName());
|
||||
}).onFailure(failure -> {
|
||||
Logging.fine("World regen failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
},
|
||||
this.commandManager.formatMessage(
|
||||
issuer, MessageType.INFO, MVCorei18n.REGEN_PROMPT, "{world}", world.getName())));
|
||||
}
|
||||
}
|
||||
@@ -14,28 +14,30 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.anchor.AnchorManager;
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.config.CoreConfig;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.config.MVCoreConfig;
|
||||
import org.mvplugins.multiverse.core.event.MVConfigReloadEvent;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
|
||||
@Service
|
||||
class ReloadCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class ReloadCommand extends MultiverseCommand {
|
||||
|
||||
private final CoreConfig config;
|
||||
private final MVCoreConfig config;
|
||||
private final AnchorManager anchorManager;
|
||||
private final WorldManager worldManager;
|
||||
private final PluginManager pluginManager;
|
||||
|
||||
@Inject
|
||||
ReloadCommand(
|
||||
@NotNull CoreConfig config,
|
||||
@NotNull MVCommandManager commandManager,
|
||||
@NotNull MVCoreConfig config,
|
||||
@NotNull AnchorManager anchorManager,
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull PluginManager pluginManager
|
||||
) {
|
||||
@NotNull PluginManager pluginManager) {
|
||||
super(commandManager);
|
||||
this.config = config;
|
||||
this.anchorManager = anchorManager;
|
||||
this.worldManager = worldManager;
|
||||
@@ -48,36 +50,24 @@ class ReloadCommand extends CoreCommand {
|
||||
void onReloadCommand(@NotNull BukkitCommandIssuer issuer) {
|
||||
issuer.sendInfo(MVCorei18n.RELOAD_RELOADING);
|
||||
try {
|
||||
// TODO: Make this all Try<Void>
|
||||
this.config.load().getOrElseThrow(e -> new RuntimeException("Failed to load config", e));
|
||||
this.worldManager.initAllWorlds().getOrElseThrow(e -> new RuntimeException("Failed to init worlds", e));
|
||||
this.anchorManager.loadAnchors().getOrElseThrow(e -> new RuntimeException("Failed to load anchors", e));
|
||||
this.anchorManager.loadAnchors();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
List<String> configsLoaded = new ArrayList<>();
|
||||
configsLoaded.add("Multiverse-Core - config.yml");
|
||||
configsLoaded.add("Multiverse-Core - worlds.yml");
|
||||
configsLoaded.add("Multiverse-Core - worlds2.yml");
|
||||
configsLoaded.add("Multiverse-Core - anchors.yml");
|
||||
|
||||
MVConfigReloadEvent configReload = new MVConfigReloadEvent(configsLoaded);
|
||||
this.pluginManager.callEvent(configReload);
|
||||
|
||||
// TODO: replace this sendMessage and format the configsLoaded above, maybe?
|
||||
configReload.getAllConfigsLoaded().forEach(issuer::sendMessage);
|
||||
issuer.sendInfo(MVCorei18n.RELOAD_SUCCESS);
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends ReloadCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull CoreConfig config, @NotNull AnchorManager anchorManager, @NotNull WorldManager worldManager, @NotNull PluginManager pluginManager) {
|
||||
super(config, anchorManager, worldManager, pluginManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvreload|mvr")
|
||||
void onReloadCommand(@NotNull BukkitCommandIssuer issuer) {
|
||||
super.onReloadCommand(issuer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,9 @@ package org.mvplugins.multiverse.core.commands;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Conditions;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Single;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
@@ -12,112 +13,44 @@ import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlagsManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.RemovePlayerFlags;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.utils.result.AsyncAttemptsAggregate;
|
||||
import org.mvplugins.multiverse.core.world.MultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
import org.mvplugins.multiverse.core.world.helpers.PlayerWorldTeleporter;
|
||||
import org.mvplugins.multiverse.core.world.options.RemoveWorldOptions;
|
||||
|
||||
@Service
|
||||
class RemoveCommand extends CoreCommand {
|
||||
@CommandAlias("mv")
|
||||
class RemoveCommand extends MultiverseCommand {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
private final PlayerWorldTeleporter playerWorldTeleporter;
|
||||
private final Flags flags;
|
||||
|
||||
@Inject
|
||||
RemoveCommand(
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull PlayerWorldTeleporter playerWorldTeleporter,
|
||||
@NotNull Flags flags
|
||||
) {
|
||||
RemoveCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
this.playerWorldTeleporter = playerWorldTeleporter;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Subcommand("remove")
|
||||
@CommandPermission("multiverse.core.remove")
|
||||
@CommandCompletion("@mvworlds:scope=both @flags:groupName=" + Flags.NAME)
|
||||
@CommandCompletion("@mvworlds:scope=both")
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.remove.description}")
|
||||
void onRemoveCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Single
|
||||
@Conditions("mvworlds:scope=both")
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.remove.world.description}")
|
||||
MultiverseWorld world,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--remove-players]")
|
||||
@Description("")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
|
||||
var future = parsedFlags.hasFlag(flags.removePlayers)
|
||||
? worldManager.getLoadedWorld(world).map(playerWorldTeleporter::removeFromWorld).getOrElse(AsyncAttemptsAggregate::emptySuccess)
|
||||
: AsyncAttemptsAggregate.emptySuccess();
|
||||
|
||||
future.onSuccess(() -> doWorldRemoving(issuer, world, parsedFlags))
|
||||
.onFailure(() -> issuer.sendError("Failed to teleport one or more players out of the world!"));
|
||||
}
|
||||
|
||||
private void doWorldRemoving(MVCommandIssuer issuer, MultiverseWorld world, ParsedCommandFlags parsedFlags) {
|
||||
worldManager.removeWorld(RemoveWorldOptions.world(world)
|
||||
.saveBukkitWorld(!parsedFlags.hasFlag(flags.noSave))
|
||||
.unloadBukkitWorld(!parsedFlags.hasFlag(flags.noUnloadBukkitWorld)))
|
||||
String worldName) {
|
||||
worldManager.removeWorld(worldName)
|
||||
.onSuccess(removedWorldName -> {
|
||||
Logging.fine("World remove success: " + removedWorldName);
|
||||
issuer.sendInfo(MVCorei18n.REMOVE_SUCCESS, Replace.WORLD.with(removedWorldName));
|
||||
issuer.sendInfo(MVCorei18n.REMOVEWORLD_REMOVED, "{world}", removedWorldName);
|
||||
}).onFailure(failure -> {
|
||||
Logging.fine("World remove failure: " + failure);
|
||||
issuer.sendError(failure.getFailureMessage());
|
||||
});
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class Flags extends RemovePlayerFlags {
|
||||
|
||||
private static final String NAME = "mvremove";
|
||||
|
||||
@Inject
|
||||
private Flags(@NotNull CommandFlagsManager flagsManager) {
|
||||
super(NAME, flagsManager);
|
||||
}
|
||||
|
||||
private final CommandFlag noUnloadBukkitWorld = flag(CommandFlag.builder("--no-unload-bukkit-world")
|
||||
.addAlias("-b")
|
||||
.build());
|
||||
|
||||
private final CommandFlag noSave = flag(CommandFlag.builder("--no-save")
|
||||
.addAlias("-n")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends RemoveCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull PlayerWorldTeleporter playerWorldTeleporter,
|
||||
@NotNull Flags flags
|
||||
) {
|
||||
super(worldManager, playerWorldTeleporter, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvremove")
|
||||
void onRemoveCommand(MVCommandIssuer issuer, MultiverseWorld world, String[] flags) {
|
||||
super.onRemoveCommand(issuer, world, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,16 +9,18 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.MultiverseCore;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
|
||||
import org.mvplugins.multiverse.core.utils.MVCorei18n;
|
||||
|
||||
@Service
|
||||
final class RootCommand extends CoreCommand {
|
||||
class RootCommand extends MultiverseCommand {
|
||||
|
||||
private final Plugin plugin;
|
||||
|
||||
@Inject
|
||||
RootCommand(@NotNull MultiverseCore plugin) {
|
||||
RootCommand(@NotNull MVCommandManager commandManager, @NotNull MultiverseCore plugin) {
|
||||
super(commandManager);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.LegacyAliasCommand;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.context.PlayerLocation;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.UnsafeFlags;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.teleportation.BlockSafety;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
|
||||
@Service
|
||||
class SetSpawnCommand extends CoreCommand {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
private final BlockSafety blockSafety;
|
||||
private final UnsafeFlags flags;
|
||||
|
||||
@Inject
|
||||
SetSpawnCommand(@NotNull WorldManager worldManager, @NotNull BlockSafety blockSafety, @NotNull UnsafeFlags flags) {
|
||||
this.worldManager = worldManager;
|
||||
this.blockSafety = blockSafety;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@CommandAlias("mvsetspawn")
|
||||
@Subcommand("setspawn")
|
||||
@CommandPermission("multiverse.core.spawn.set")
|
||||
@CommandCompletion("@flags:groupName=" + UnsafeFlags.NAME + " @flags:resolveUntil=arg1,groupName=" + UnsafeFlags.NAME)
|
||||
@Syntax("[worldname:x,y,z[,pitch,yaw]] [--unsafe]")
|
||||
@Description("{@@mv-core.setspawn.description}")
|
||||
void onSetSpawnCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Syntax("[worldname:x,y,z[,pitch,yaw]]")
|
||||
@Description("{@@mv-core.setspawn.location.description}")
|
||||
PlayerLocation playerLocation,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--unsafe]")
|
||||
@Description("")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
Location location = playerLocation.value();
|
||||
|
||||
if (!parsedFlags.hasFlag(flags.unsafe) && !blockSafety.canSpawnAtLocationSafely(location)) {
|
||||
issuer.sendMessage(MVCorei18n.SETSPAWN_UNSAFE);
|
||||
return;
|
||||
}
|
||||
|
||||
worldManager.getLoadedWorld(location.getWorld())
|
||||
.peek(mvWorld -> mvWorld.setSpawnLocation(location)
|
||||
.andThenTry(worldManager::saveWorldsConfig)
|
||||
.onSuccess(ignore -> issuer.sendMessage(MVCorei18n.SETSPAWN_SUCCESS,
|
||||
Replace.WORLD.with(mvWorld.getName()),
|
||||
Replace.LOCATION.with(prettyLocation(location))))
|
||||
.onFailure(e -> issuer.sendMessage(MVCorei18n.SETSPAWN_FAILED,
|
||||
Replace.WORLD.with(mvWorld.getName()),
|
||||
Replace.ERROR.with(e))))
|
||||
.onEmpty(() -> issuer.sendMessage(MVCorei18n.SETSPAWN_NOTMVWORLD,
|
||||
Replace.WORLD.with(location.getWorld().getName())));
|
||||
}
|
||||
|
||||
private String prettyLocation(Location location) {
|
||||
return "%.2f, %.2f, %.2f, pitch:%.2f, yaw:%.2f"
|
||||
.formatted(location.getX(), location.getY(), location.getZ(), location.getPitch(), location.getYaw());
|
||||
}
|
||||
|
||||
@Service
|
||||
private static final class LegacyAlias extends SetSpawnCommand implements LegacyAliasCommand {
|
||||
@Inject
|
||||
LegacyAlias(@NotNull WorldManager worldManager, @NotNull BlockSafety blockSafety, @NotNull UnsafeFlags flags) {
|
||||
super(worldManager, blockSafety, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CommandAlias("mvss")
|
||||
void onSetSpawnCommand(MVCommandIssuer issuer, PlayerLocation location, String[] flagArray) {
|
||||
super.onSetSpawnCommand(issuer, location, flagArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
package org.mvplugins.multiverse.core.commands;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Flags;
|
||||
import co.aikar.commands.annotation.Optional;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
|
||||
import org.mvplugins.multiverse.core.command.MVCommandManager;
|
||||
import org.mvplugins.multiverse.core.command.flag.CommandFlag;
|
||||
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
|
||||
import org.mvplugins.multiverse.core.command.flags.UnsafeFlags;
|
||||
import org.mvplugins.multiverse.core.locale.MVCorei18n;
|
||||
import org.mvplugins.multiverse.core.locale.message.Message;
|
||||
import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace;
|
||||
import org.mvplugins.multiverse.core.permissions.CorePermissionsChecker;
|
||||
import org.mvplugins.multiverse.core.teleportation.AsyncSafetyTeleporter;
|
||||
import org.mvplugins.multiverse.core.teleportation.TeleportFailureReason;
|
||||
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
|
||||
import org.mvplugins.multiverse.core.world.WorldManager;
|
||||
|
||||
@Service
|
||||
final class SpawnCommand extends CoreCommand {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
private final AsyncSafetyTeleporter safetyTeleporter;
|
||||
private final CorePermissionsChecker permissionsChecker;
|
||||
private final UnsafeFlags flags;
|
||||
|
||||
@Inject
|
||||
SpawnCommand(
|
||||
@NotNull WorldManager worldManager,
|
||||
@NotNull AsyncSafetyTeleporter safetyTeleporter,
|
||||
@NotNull CorePermissionsChecker permissionsChecker,
|
||||
@NotNull UnsafeFlags flags
|
||||
) {
|
||||
this.worldManager = worldManager;
|
||||
this.safetyTeleporter = safetyTeleporter;
|
||||
this.permissionsChecker = permissionsChecker;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@CommandAlias("mvspawn")
|
||||
@Subcommand("spawn")
|
||||
@CommandPermission("@mvspawn")
|
||||
@CommandCompletion("@playersarray:checkPermissions=@mvspawnother|@flags:resolveUntil=arg1,groupName=" + UnsafeFlags.NAME
|
||||
+ " @flags:groupName=" + UnsafeFlags.NAME)
|
||||
@Syntax("[player]")
|
||||
@Description("{@@mv-core.spawn.description}")
|
||||
void onSpawnTpCommand(
|
||||
MVCommandIssuer issuer,
|
||||
|
||||
@Flags("resolve=issuerAware")
|
||||
@Syntax("[player]")
|
||||
@Description("{@@mv-core.spawn.player.description}")
|
||||
Player[] players,
|
||||
|
||||
@Optional
|
||||
@Syntax("[--unsafe]")
|
||||
@Description("")
|
||||
String[] flagArray) {
|
||||
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
|
||||
|
||||
Map<World, List<Entity>> playersByWorld = Arrays.stream(players)
|
||||
.collect(Collectors.groupingBy(Entity::getWorld));
|
||||
playersByWorld.forEach((world, entities) ->
|
||||
teleportPlayersToSpawn(issuer, world, entities, !parsedFlags.hasFlag(flags.unsafe)));
|
||||
}
|
||||
|
||||
private void teleportPlayersToSpawn(MVCommandIssuer issuer, World world,
|
||||
List<Entity> entities, boolean checkSafety) {
|
||||
LoadedMultiverseWorld mvWorld = worldManager.getLoadedWorld(world).getOrNull();
|
||||
if (mvWorld == null) {
|
||||
issuer.sendMessage("The world '" + world.getName() + "' is not a multiverse world!");
|
||||
return;
|
||||
}
|
||||
if (!permissionsChecker.checkSpawnPermission(issuer.getIssuer(), entities, mvWorld)) {
|
||||
issuer.sendMessage("You do not have permission to use this command in this world!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (entities.size() == 1) {
|
||||
handleSingleTeleport(issuer, mvWorld, entities.get(0), checkSafety);
|
||||
} else {
|
||||
handleMultiTeleport(issuer, mvWorld, entities, checkSafety);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSingleTeleport(MVCommandIssuer issuer, LoadedMultiverseWorld mvWorld,
|
||||
Entity entity, boolean checkSafety) {
|
||||
safetyTeleporter.to(mvWorld.getSpawnLocation())
|
||||
.by(issuer)
|
||||
.checkSafety(checkSafety)
|
||||
.teleportSingle(entity)
|
||||
.onSuccess(() -> issuer.sendInfo(MVCorei18n.SPAWN_SUCCESS,
|
||||
Replace.PLAYER.with(entity.equals(issuer.getPlayer())
|
||||
? Message.of(MVCorei18n.GENERIC_YOU)
|
||||
: Message.of(entity.getName())),
|
||||
Replace.WORLD.with(mvWorld.getName())))
|
||||
.onFailure(failure -> issuer.sendError(MVCorei18n.SPAWN_FAILED,
|
||||
Replace.PLAYER.with(entity.equals(issuer.getPlayer())
|
||||
? Message.of(MVCorei18n.GENERIC_YOU)
|
||||
: Message.of(entity.getName())),
|
||||
Replace.WORLD.with(mvWorld.getName()),
|
||||
Replace.REASON.with(failure.get(0).getFailureMessage())));
|
||||
}
|
||||
|
||||
private void handleMultiTeleport(MVCommandIssuer issuer, LoadedMultiverseWorld mvWorld,
|
||||
List<Entity> entities, boolean checkSafety) {
|
||||
safetyTeleporter.to(mvWorld.getSpawnLocation())
|
||||
.by(issuer)
|
||||
.checkSafety(checkSafety)
|
||||
.teleport(entities)
|
||||
.onSuccessCount(successCount -> issuer.sendMessage(MVCorei18n.SPAWN_SUCCESS,
|
||||
Replace.PLAYER.with(successCount + " players"), //todo: replace this with localised "{count} players"
|
||||
Replace.WORLD.with(mvWorld.getName())))
|
||||
.onFailureCount(reasonsCountMap -> {
|
||||
for (var entry : reasonsCountMap.entrySet()) {
|
||||
Logging.finer("Failed to teleport %s players to %s: %s",
|
||||
entry.getValue(), mvWorld.getName(), entry.getKey());
|
||||
issuer.sendError(MVCorei18n.SPAWN_FAILED,
|
||||
Replace.PLAYER.with(entry.getValue() + " players"),
|
||||
Replace.WORLD.with(mvWorld.getName()),
|
||||
Replace.REASON.with(entry.getKey().getMessageKey()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Loaded 100 of 443 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user