Compare commits

..
Author SHA1 Message Date
Ben Woo 2754c6ea0d Use version dbo-upload-action v0.1.0 2023-08-20 21:22:22 +08:00
Ben Woo ef6cd16e91 Remove end comma 2023-08-20 21:02:04 +08:00
Ben Woo b2691e979e Better format for project relation 2023-08-20 21:01:29 +08:00
Ben Woo 21e905fc83 Remove some game version that DBO doesnt have 2023-08-20 20:26:00 +08:00
Ben Woo bd6c44279d use game version by name 2023-08-20 20:13:22 +08:00
Ben Woo 743e741a92 Remove the fail 2023-08-20 16:36:17 +08:00
Ben Woo d841d9d5d0 Test without to json 2023-08-20 16:34:35 +08:00
Ben Woo 32d0e39866 Fix display name version 2023-08-20 16:28:04 +08:00
Ben Woo 71fe3de39a Use output version 2023-08-20 16:14:46 +08:00
Ben Woo b973292d0e Fix some upload field keys 2023-08-20 15:53:24 +08:00
Ben Woo 6db2cc25d6 Fix typo multiverse 2023-08-20 15:46:22 +08:00
Ben Woo c24777d282 Update regex 2023-08-20 15:45:29 +08:00
Ben Woo eeb58a05b1 Use regex 2023-08-20 15:41:39 +08:00
Ben Woo 0dd8ecaa84 Use latest version and fix copy paste issue 2023-08-20 15:39:49 +08:00
Ben Woo 01cc8e5177 Try dbo upload action 2023-08-20 15:36:10 +08:00
370 changed files with 11073 additions and 16422 deletions

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
prerelease:
- '*'
-34
View File
@@ -1,34 +0,0 @@
name: 'Call: GitHub Release'
on:
workflow_call:
inputs:
release_mode:
description: 'Release mode'
required: true
type: string
version_bump:
description: 'Version bump'
required: false
type: string
promote_from:
description: 'Promote from'
required: false
type: string
outputs:
release_created:
description: 'Release created'
value: ${{ jobs.github_release.outputs.release_created }}
tag_name:
description: 'Tag name'
value: ${{ jobs.github_release.outputs.tag_name }}
jobs:
github_release:
uses: ./.github/workflows/generic.github_release.yml
secrets: inherit
with:
plugin_name: multiverse-core
release_mode: ${{ inputs.release_mode }}
version_bump: ${{ inputs.version_bump }}
promote_from: ${{ inputs.promote_from }}
@@ -1,83 +0,0 @@
name: 'Call: Platform Uploads'
on:
workflow_call:
inputs:
target_tag:
description: 'Version to upload'
required: true
type: string
upload_modrinth:
description: 'Upload to modrinth.com'
required: true
type: string
upload_dbo:
description: 'Upload to dev.bukkit.org'
required: true
type: string
upload_hangar:
description: 'Upload to hangar.papermc.io'
required: true
type: string
secrets:
MODRINTH_TOKEN:
required: true
DBO_UPLOAD_API_TOKEN:
required: true
HANGAR_UPLOAD_TOKEN:
required: true
jobs:
platform_uploads:
uses: ./.github/workflows/generic.platform_uploads.yml
secrets: inherit
with:
plugin_name: multiverse-core
modrinth_project_id: 3wmN97b8
modrinth_dependencies: >
[
{"project_id": "qvdtDX3s", "dependency_type": "optional"},
{"project_id": "8VMk6P0I", "dependency_type": "optional"},
{"project_id": "vtawPsTo", "dependency_type": "optional"},
{"project_id": "WuErDeI1", "dependency_type": "optional"}
]
dbo_project_id: 30765
dbo_project_relations: >
[
{"slug": "multiverse-inventories", "type": "optionalDependency"},
{"slug": "multiverse-portals", "type": "optionalDependency"},
{"slug": "multiverse-netherportals", "type": "optionalDependency"},
{"slug": "multiverse-signportals", "type": "optionalDependency"},
{"slug": "vault", "type": "optionalDependency"}
]
hangar_slug: Multiverse-Core
hangar_plugin_dependencies: >
{ "PAPER": [
{
"name": "Multiverse-Inventories",
"required": false,
"platforms": ["PAPER"]
},
{
"name": "Multiverse-Portals",
"required": false,
"platforms": ["PAPER"]
},
{
"name": "Multiverse-NetherPortals",
"required": false,
"platforms": ["PAPER"]
},
{
"name": "Multiverse-SignPortals",
"required": false,
"platforms": ["PAPER"]
}
]}
target_tag: ${{ inputs.target_tag }}
upload_modrinth: ${{ inputs.upload_modrinth }}
upload_dbo: ${{ inputs.upload_dbo }}
upload_hangar: ${{ inputs.upload_hangar }}
+38
View File
@@ -0,0 +1,38 @@
name: Create Release Version & Publish Package
on:
push:
branches: [dbo-test]
jobs:
dbo_upload_test:
runs-on: ubuntu-latest
steps:
- name: Download release artifact
id: release-artifact
uses: dsaltares/fetch-gh-release-asset@master
with:
token: ${{ secrets.GITHUB_TOKEN }}
# version: tags/${{ github.event.inputs.version }}
regex: true
file: multiverse-core-(.*)\.jar
target: 'subdir/'
- name: Upload to dev.bukkit.org
uses: benwoo1110/dbo-upload-action@v0.1.0
with:
api_token: ${{ secrets.DBO_UPLOAD_API_TOKEN }}
project_id: 30765
changelog: ${{ steps.release-artifact.outputs.body }}
changelog_type: markdown
display_name: ${{ steps.release-artifact.outputs.version }}
game_versions: 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.18.1, 1.18.2, 1.19, 1.19.1, 1.19.2, 1.19.3, 1.19.4, 1.20, 1.20.1
project_relations: >
[
{"slug": "multiverse-portals", "type": "optionalDependency"},
{"slug": "multiverse-netherportals", "type": "optionalDependency"},
{"slug": "multiverse-signportals", "type": "optionalDependency"},
{"slug": "multiverse-inventories", "type": "optionalDependency"}
]
file_path: ${{ github.workspace }}/subdir/multiverse-core-${{ steps.release-artifact.outputs.version }}.jar
debug: true
@@ -1,31 +0,0 @@
name: 'Dispatch: Platform Uploads'
on:
workflow_dispatch:
inputs:
target_tag:
description: 'Version to upload'
required: true
type: string
upload_modrinth:
description: 'Upload to modrinth.com'
required: true
type: boolean
upload_dbo:
description: 'Upload to dev.bukkit.org'
required: true
type: boolean
upload_hangar:
description: 'Upload to hangar.papermc.io'
required: true
type: boolean
jobs:
dispatch_platform_uploads:
uses: ./.github/workflows/call.platform_uploads.yml
secrets: inherit
with:
target_tag: ${{ github.event.inputs.target_tag }}
upload_modrinth: ${{ github.event.inputs.upload_modrinth }}
upload_dbo: ${{ github.event.inputs.upload_dbo }}
upload_hangar: ${{ github.event.inputs.upload_hangar }}
@@ -1,38 +0,0 @@
name: 'Dispatch: Promote Release'
on:
workflow_dispatch:
inputs:
target_tag:
description: 'Version to promote'
required: true
jobs:
check_version:
runs-on: ubuntu-latest
steps:
- name: Verify input version is prerelease
run: |
if [[ "${{ github.event.inputs.target_tag }}" != *"pre"* ]]; then
echo "Version must be a prerelease"
exit 1
fi
github_release:
needs: check_version
uses: ./.github/workflows/call.github_release.yml
secrets: inherit
with:
release_mode: promote
promote_from: ${{ github.event.inputs.target_tag }}
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: 'true'
upload_hangar: 'true'
-22
View File
@@ -1,22 +0,0 @@
name: 'Generic: Checkstyle'
on:
workflow_call:
jobs:
checkstyle:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
continue-on-error: true
steps:
- uses: actions/checkout@v3
- uses: dbelyaev/action-checkstyle@v0.8.4
continue-on-error: true
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
checkstyle_version: 10.12.2
checkstyle_config: ./config/mv_checks.xml
level: warning
@@ -1,91 +0,0 @@
name: 'Generic: GitHub Release'
on:
workflow_call:
inputs:
# Plugin specific
plugin_name:
description: 'Plugin name'
required: true
type: string
# Common params
release_mode:
description: 'Release mode'
required: true
type: string
version_bump:
description: 'Version bump'
required: false
type: string
promote_from:
description: 'Promote from'
required: false
type: string
outputs:
release_created:
description: 'Release created'
value: ${{ jobs.github_release.outputs.release_created }}
tag_name:
description: 'Tag name'
value: ${{ jobs.github_release.outputs.tag_name }}
jobs:
github_release:
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
- name: Echo inputs
run: |
echo "release_mode: ${{ inputs.release_mode }}"
echo "version_bump: ${{ inputs.version_bump }}"
echo "promote_from: ${{ inputs.promote_from }}"
- uses: actions/checkout@v3
with:
ref: ${{ inputs.promote_from }}
- uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'adopt'
cache: gradle
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@v1
- 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
uses: benwoo1110/semantic-release-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
release_mode: ${{ inputs.release_mode }}
version_bump: ${{ inputs.version_bump }}
promote_from: ${{ inputs.promote_from }}
- name: Publish package
if: steps.release.outputs.release_created == 'true'
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: Upload release artifact
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.publish_version }}.jar
asset_name: ${{ inputs.plugin_name }}-${{ steps.release.outputs.tag_name }}.jar
tag: ${{ steps.release.outputs.tag_name }}
@@ -1,140 +0,0 @@
name: 'Generic: Platform Uploads'
on:
workflow_call:
inputs:
# Plugin specific params
plugin_name:
description: 'Plugin name'
required: true
type: string
modrinth_project_id:
description: 'modrinth.com project ID'
required: true
type: string
modrinth_dependencies:
description: 'modrinth.com project dependencies'
required: false
type: string
default: '[]'
dbo_project_id:
description: 'dev.bukkit.org project ID'
required: true
type: string
dbo_project_relations:
description: 'dev.bukkit.org project relations'
required: false
type: string
default: '[]'
hangar_slug:
description: 'hangar.papermc.io project slug'
required: true
type: string
hangar_plugin_dependencies:
description: 'hangar.papermc.io project dependencies'
required: false
type: string
default: '{}'
# Common params
target_tag:
description: 'Version to upload'
required: true
type: string
upload_modrinth:
description: 'Upload to modrinth.com'
required: true
type: string
upload_dbo:
description: 'Upload to dev.bukkit.org'
required: true
type: string
upload_hangar:
description: 'Upload to hangar.papermc.io'
required: true
type: string
secrets:
MODRINTH_TOKEN:
required: true
DBO_UPLOAD_API_TOKEN:
required: true
HANGAR_UPLOAD_TOKEN:
required: true
jobs:
platform_uploads:
runs-on: ubuntu-latest
steps:
- name: Get release info
id: release-info
uses: cardinalby/git-get-release-action@1.2.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag: ${{ inputs.target_tag }}
- name: Download release artifact
id: release-artifact
uses: dsaltares/fetch-gh-release-asset@1.1.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
version: tags/${{ steps.release-info.outputs.tag_name }}
file: ${{ inputs.plugin_name }}-${{ steps.release-info.outputs.tag_name }}.jar
- name: Parse release type
id: parse-release-type
run: |
if [[ "${{ steps.release-info.outputs.prerelease }}" == "true" ]]; then
echo Setting release_type to Beta
echo "release_type=Beta" >> $GITHUB_OUTPUT
else
echo Setting release_type to Release
echo "release_type=Release" >> $GITHUB_OUTPUT
fi
- name: Upload to Modrinth
if: ${{ !cancelled() && inputs.upload_modrinth == 'true' }}
uses: benwoo1110/modrinth-upload-action@v1
with:
api_token: ${{ secrets.MODRINTH_TOKEN }}
project_id: ${{ inputs.modrinth_project_id }}
version_number: ${{ steps.release-info.outputs.tag_name }}
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.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
dependencies: ${{ inputs.modrinth_dependencies }}
- name: Upload to DBO
if: ${{ !cancelled() && inputs.upload_dbo == 'true' }}
uses: benwoo1110/dbo-upload-action@v1
with:
api_token: ${{ secrets.DBO_UPLOAD_API_TOKEN }}
project_id: ${{ inputs.dbo_project_id }}
changelog: ${{ steps.release-artifact.outputs.body }}
changelog_type: markdown
display_name: ${{ steps.release-info.outputs.tag_name }}
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
- name: Upload to Hangar
if: ${{ !cancelled() && inputs.upload_hangar == 'true' }}
uses: benwoo1110/hangar-upload-action@v1
with:
api_token: ${{ secrets.HANGAR_UPLOAD_TOKEN }}
slug: ${{ inputs.hangar_slug }}
version: ${{ steps.release-info.outputs.tag_name }}
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.13-1.20.1"]}'
plugin_dependencies: ${{ inputs.hangar_plugin_dependencies }}
-24
View File
@@ -1,24 +0,0 @@
name: 'Main: Prerelease'
on:
push:
branches: [main]
jobs:
github_release_on_push:
uses: ./.github/workflows/call.github_release.yml
secrets: inherit
with:
release_mode: prerelease
version_bump: prlabel
platform_uploads_on_push:
needs: github_release_on_push
if: needs.github_release_on_push.outputs.release_created == 'true'
uses: ./.github/workflows/call.platform_uploads.yml
secrets: inherit
with:
target_tag: ${{ needs.github_release_on_push.outputs.tag_name }}
upload_modrinth: 'true'
upload_dbo: 'false'
upload_hangar: 'false'
-9
View File
@@ -1,9 +0,0 @@
name: 'PR: Checkstyle'
on:
pull_request:
types: [opened, synchronize]
jobs:
checkstyle:
uses: ./.github/workflows/generic.checkstyle.yml
-11
View File
@@ -1,11 +0,0 @@
name: 'PR: Test'
on:
pull_request:
types: [opened, synchronize]
jobs:
test:
uses: ./.github/workflows/generic.test.yml
with:
plugin_name: multiverse-core
+17
View File
@@ -0,0 +1,17 @@
name: "Pull Request Labeler"
on:
pull_request_target:
types: [opened]
branches: [main]
jobs:
prerelease_labeler:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
+90
View File
@@ -0,0 +1,90 @@
name: Manually promote last prerelease to release
on:
workflow_dispatch:
inputs:
version:
description: 'Version to promote'
required: true
version-bump:
description: 'Version bump to apply - should usually match the version bump used for the prerelease since last release'
required: true
type: choice
options:
- 'patch'
- 'minor'
- 'major'
jobs:
manually_promote_release:
runs-on: ubuntu-latest
steps:
- name: Verify input version is prerelease
run: |
if [[ "${{ github.event.inputs.version }}" != *"pre"* ]]; then
echo "Version must be a prerelease"
exit 1
fi
- name: Get release info
id: get-release
uses: cardinalby/git-get-release-action@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
tag: ${{ github.event.inputs.version }}
- uses: actions/checkout@v3
with:
ref: ${{ steps.get-release.outputs.tag_name }}
- uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
cache: gradle
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: Remove prerelease tag
run: |
echo "Removing prerelease tag from version"
echo "VERSION=$(echo ${{ steps.get-release.outputs.tag_name }} | sed -E 's/-pre.*//')" >> $GITHUB_ENV
- name: Build
uses: gradle/gradle-build-action@v2
with:
arguments: clean build -x test -x checkstyleMain -x checkstyleTest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_VERSION: ${{ env.VERSION }}
- name: Create release
id: release
uses: Multiverse/release-on-push-action@skip_prs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
bump_version_scheme: ${{ github.event.inputs.version-bump }}
tag_prefix: ''
release_name: "<RELEASE_VERSION>"
use_github_release_notes: true
ref: ${{ steps.get-release.outputs.target_commitish }}
skip_prs: true
- name: Publish package
uses: gradle/gradle-build-action@v2
with:
arguments: publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_VERSION: ${{ env.VERSION }}
- name: Upload release artifact
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: build/libs/multiverse-core-${{ env.VERSION }}.jar
asset_name: multiverse-core-${{ steps.release.outputs.tag_name }}.jar
tag: ${{ steps.release.outputs.tag_name }}
+64
View File
@@ -0,0 +1,64 @@
name: Create Release Version & Publish Package
on:
push:
branches: [main]
jobs:
release_on_push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
cache: gradle
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: Test & Build
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
uses: Multiverse/release-on-push-action@support_prerelease
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
bump_version_scheme: norelease
tag_prefix: ''
release_name: "<RELEASE_VERSION>"
use_github_release_notes: true
- name: Modify version scheme
run: |
if [[ "${{ steps.release.outputs.tag_name }}" == *"pre"* ]]; then
echo "Replacing prerelease version scheme with SNAPSHOT"
echo "VERSION=$(echo ${{ steps.release.outputs.tag_name }} | sed -E 's/-pre.*/-SNAPSHOT/')" >> $GITHUB_ENV
else
echo "Using release version scheme"
echo "VERSION=${{ steps.release.outputs.tag_name }}" >> $GITHUB_ENV
fi
- name: Publish package
uses: gradle/gradle-build-action@v2
with:
arguments: publish
env:
GITHUB_VERSION: ${{ env.VERSION }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload release artifact
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: build/libs/multiverse-core-${{ env.VERSION }}.jar
asset_name: multiverse-core-${{ steps.release.outputs.tag_name }}.jar
tag: ${{ steps.release.outputs.tag_name }}
@@ -1,4 +1,4 @@
name: 'PR: Require Label'
name: Require PR Labels
on:
pull_request:
@@ -15,4 +15,4 @@ jobs:
with:
mode: exactly
count: 1
labels: "release:major, release:minor, release:patch, no release"
labels: "release:major, release:minor, release:patch, no version bump"
@@ -1,12 +1,8 @@
name: 'Generic: Test'
name: Run unit tests against all PRs
on:
workflow_call:
inputs:
plugin_name:
description: 'Plugin name'
required: true
type: string
pull_request:
types: [opened, synchronize]
jobs:
test:
@@ -28,7 +24,7 @@ jobs:
- name: Run unit tests
uses: gradle/gradle-build-action@v2
with:
arguments: build
arguments: build -x checkstyleMain -x checkstyleTest -x javadoc
env:
GITHUB_VERSION: pr${{ github.event.pull_request.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -36,5 +32,5 @@ jobs:
- name: Artifact output
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
name: multiverse-core-pr${{ github.event.pull_request.number }}
path: build/libs/multiverse-core-pr${{ github.event.pull_request.number }}.jar
+18 -24
View File
@@ -1,33 +1,26 @@
<p align="center">
<img src="config/multiverse2-long.png" alt="Multiverse Logo">
</p>
![Multiverse 2](config/multiverse2-long.png)
[![Modrinth](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/available/modrinth_vector.svg)](https://modrinth.com/plugin/multiverse-core)
[![hangar](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/available/hangar_vector.svg)](https://hangar.papermc.io/Multiverse/Multiverse-Core)
[![bukkit](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/supported/bukkit_vector.svg)](https://dev.bukkit.org/projects/multiverse-core)
[![Spigot](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/supported/spigot_vector.svg)](https://www.spigotmc.org/resources/multiverse-core.390/)
[![Release](https://img.shields.io/nexus/r/com.onarandombox.multiversecore/multiverse-core?server=https%3A%2F%2Frepo.onarandombox.com&label=release&color=dark-green)](https://dev.bukkit.org/projects/multiverse-core)
[![Dev builds](https://img.shields.io/nexus/s/com.onarandombox.multiversecore/multiverse-core?server=https%3A%2F%2Frepo.onarandombox.com&label=prerelease&color=orange)](https://ci.onarandombox.com/job/Multiverse-Core/)
[![Maven CI/CD](https://github.com/Multiverse/Multiverse-Core/actions/workflows/build.yml/badge.svg)](https://github.com/Multiverse/Multiverse-Core/actions/workflows/build.yml)
[![Release](https://img.shields.io/nexus/r/com.onarandombox.multiversecore/Multiverse-Core?label=release&server=https%3A%2F%2Frepo.onarandombox.com%2F)](https://dev.bukkit.org/projects/multiverse-core)
[![Dev builds](https://img.shields.io/nexus/s/com.onarandombox.multiversecore/Multiverse-Core?label=dev%20builds&server=http%3A%2F%2Frepo.onarandombox.com%2F)](https://ci.onarandombox.com/job/Multiverse-Core/)
[![Discord](https://img.shields.io/discord/325459248047980545?label=discord&logo=discord)](https://discord.gg/NZtfKky)
[![Support us on Patreon](https://img.shields.io/badge/donate-patreon-white?logo=patreon)](https://patreon.com/dumptruckman)
[![License](https://img.shields.io/github/license/Multiverse/Multiverse-Core?color=blue)](LICENSE.md)
# About
[![Support me on Patreon](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Ddumptruckman%26type%3Dpatrons&style=flat)](https://patreon.com/dumptruckman)
[![License](https://img.shields.io/github/license/Multiverse/Multiverse-Core)](LICENSE.md)
About
========
[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!
<br><br>
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!
## Amazing sub-modules available:
### Amazing sub-modules available:
* [Multiverse-NetherPortals](https://github.com/Multiverse/Multiverse-NetherPortals) -> Have separate nether and end worlds for each of your overworlds!
* [Multiverse-Portals](https://github.com/Multiverse/Multiverse-Portals) -> Make custom portals to go to any destination!
* [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!
* [Multiverse-SignPortals](https://github.com/Multiverse/Multiverse-SignPortals) -> Signs as teleprompters!
## Building
Building
========
Simply build the source with Gradle:
```
./gradlew build
@@ -35,16 +28,17 @@ Simply build the source with Gradle:
More details are available on the [build instructions wiki page](https://github.com/Multiverse/Multiverse-Core/wiki/Building).
## Contributing
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-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 joining our [Patreon](https://www.patreon.com/dumptruckman) or make a one-time donation [here](https://paypal.me/dumptruckman)!
* 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!
## License
License
=======
Multiverse-Core is licensed under BSD-3-Clause License. Please see [LICENSE.md](LICENSE.md) for more info.
+51 -86
View File
@@ -3,6 +3,7 @@ import org.apache.tools.ant.filters.ReplaceTokens
plugins {
id 'java-library'
id 'maven-publish'
id 'checkstyle'
id 'com.github.johnrengelman.shadow' version '7.1.2'
id "org.jetbrains.kotlin.jvm" version "1.8.10"
}
@@ -54,75 +55,61 @@ repositories {
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
relocatedApi
compileClasspath.extendsFrom relocatedApi
runtimeClasspath.extendsFrom relocatedApi
testCompileClasspath.extendsFrom relocatedApi
testRuntimeClasspath.extendsFrom relocatedApi
oldTestCompileClasspath.extendsFrom relocatedApi
oldTestRuntimeClasspath.extendsFrom relocatedApi
}
dependencies {
serverApi 'org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT'
compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
// Economy
externalPlugin('com.github.MilkBowl:VaultAPI:1.7.1') {
implementation('com.github.MilkBowl:VaultAPI:1.7.1') {
exclude group: 'org.bukkit', module: 'bukkit'
}
// PlaceholderAPI
externalPlugin 'me.clip:placeholderapi:2.11.3'
implementation 'me.clip:placeholderapi:2.11.3'
// Command Framework
shadowed 'co.aikar:acf-paper:0.5.1-SNAPSHOT'
relocatedApi 'co.aikar:acf-paper:0.5.1-SNAPSHOT'
// Config
shadowed('me.main__.util:SerializationConfig:1.7') {
relocatedApi('me.main__.util:SerializationConfig:1.7') {
exclude group: 'org.bukkit', module: 'bukkit'
}
shadowed('io.github.townyadvanced.commentedconfiguration:CommentedConfiguration:1.0.1') {
relocatedApi('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') {
relocatedApi 'io.vavr:vavr:0.10.4'
relocatedApi 'org.glassfish.hk2:hk2-locator:3.0.3'
relocatedApi('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'
relocatedApi 'de.themoep.idconverter:mappings:1.2-SNAPSHOT'
relocatedApi 'org.bstats:bstats-bukkit:2.2.1'
relocatedApi 'net.minidev:json-smart:2.4.8'
relocatedApi 'org.jetbrains:annotations:22.0.0'
relocatedApi '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.github.seeseemelk:MockBukkit-v1.19:2.141.0'
testImplementation('com.googlecode.json-simple:json-simple:1.1.1') {
exclude group: 'junit', module: 'junit'
}
@@ -131,7 +118,7 @@ dependencies {
testImplementation 'org.mockito.kotlin:mockito-kotlin:4.1.0'
// Old Tests
oldTestImplementation 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
oldTestImplementation 'org.spigotmc:spigot-api:1.19.3-R0.1-SNAPSHOT'
oldTestImplementation('com.googlecode.json-simple:json-simple:1.1.1') {
exclude group: 'junit', module: 'junit'
}
@@ -183,34 +170,6 @@ 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 {
@@ -268,6 +227,13 @@ processResources {
}
checkstyle {
toolVersion = '6.1.1'
configFile file('config/mv_checks.xml')
ignoreFailures = true
}
javadoc {
source = sourceSets.main.allJava
classpath = configurations.compileClasspath
@@ -277,27 +243,27 @@ javadoc {
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'
relocate 'co.aikar.commands', 'com.onarandombox.acf'
relocate 'com.dumptruckman.minecraft.util.Logging', 'com.onarandombox.MultiverseCore.utils.CoreLogging'
relocate 'com.dumptruckman.minecraft.util.DebugLog', 'com.onarandombox.MultiverseCore.utils.DebugFileLogger'
relocate 'de.themoep.idconverter', 'com.onarandombox.idconverter'
relocate 'io.github.townyadvanced.commentedconfiguration', 'com.onarandombox.commentedconfiguration'
relocate 'me.main__.util', 'com.onarandombox.serializationconfig'
relocate 'org.bstats', 'com.onarandombox.bstats'
relocate 'com.sun', 'com.onarandombox.sun'
relocate 'net.minidev', 'com.onarandombox.minidev'
relocate 'org.objectweb', 'com.onarandombox.objectweb'
relocate 'io.vavr', 'com.onarandombox.vavr'
relocate 'jakarta', 'com.onarandombox.jakarta'
relocate 'javassist', 'com.onarandombox.javassist'
relocate 'org.aopalliance', 'com.onarandombox.aopalliance'
relocate 'org.glassfish', 'com.onarandombox.glassfish'
relocate 'org.jvnet', 'com.onarandombox.jvnet'
relocate 'org.intellij', 'com.onarandombox.intellij'
relocate 'org.jetbrains', 'com.onarandombox.jetbrains'
relocate 'io.papermc.lib', 'com.onarandombox.paperlib'
configurations = [project.configurations.shadowed]
configurations = [project.configurations.api, project.configurations.relocatedApi]
archiveFileName = "$baseName-$version.$extension"
@@ -306,7 +272,6 @@ shadowJar {
it.moduleGroup == 'org.jetbrains.kotlin'
})
}
//classifier = ''
}
build.dependsOn shadowJar
+90 -614
View File
@@ -6,660 +6,136 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<!-- Future reference: valid severity values are 'ignore', 'info', 'warning', 'error' -->
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="fileExtensions" value="java, properties, xml"/>
<property name="severity" value="warning"/>
<!-- Javadoc Comments -->
<module name="JavadocPackage"/><!-- require package-info.java file -->
<!-- Miscellaneous -->
<module name="JavadocPackage">
<property name="allowLegacy" value="true"/>
</module>
<module name="NewlineAtEndOfFile" />
<module name="OrderedProperties"/>
<module name="Translation"/>
<module name="UniqueProperties"/>
<!-- Regexp -->
<module name="FileLength"/>
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="RegexpSingleline">
<property name="message" value="Line has trailing spaces."/>
<property name="format" value="\s+$"/>
</module>
<!-- Size Violations -->
<module name="FileLength">
<property name="max" value="2000"/>
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="SUPPRESS CHECKSTYLE: (\w+)"/>
<property name="checkFormat" value="$1"/>
</module>
<module name="LineLength">
<property name="fileExtensions" value="java"/>
<property name="max" value="120"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="BEGIN CHECKSTYLE-SUPPRESSION\: (\w+)"/>
<property name="onCommentFormat" value="END CHECKSTYLE-SUPPRESSION\: (\w+)"/>
<property name="checkFormat" value="$1"/>
</module>
<!-- Whitespace -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="BEGIN CHECKSTYLE-SUPPRESSION\: ALL"/>
<property name="onCommentFormat" value="END CHECKSTYLE-SUPPRESSION\: ALL"/>
</module>
<module name="TreeWalker">
<!-- Make suppression possible -->
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="SUPPRESS CHECKSTYLE: (\w+)"/>
<property name="checkFormat" value="$1"/>
</module>
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="BEGIN CHECKSTYLE-SUPPRESSION\: (\w+)"/>
<property name="onCommentFormat" value="END CHECKSTYLE-SUPPRESSION\: (\w+)"/>
<property name="checkFormat" value="$1"/>
</module>
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="BEGIN CHECKSTYLE-SUPPRESSION\: ALL"/>
<property name="onCommentFormat" value="END CHECKSTYLE-SUPPRESSION\: ALL"/>
</module>
<module name="FileContentsHolder"/>
<!-- Actual checks -->
<!-- Annotations -->
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, PACKAGE_DEF, ENUM_CONSTANT_DEF,
ENUM_DEF, METHOD_DEF, CTOR_DEF, RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="AnnotationLocation"/>
<module name="AnnotationUseStyle"/>
<module name="MissingDeprecated"/>
<module name="MissingOverride"/>
<!-- Block Checks -->
<module name="AvoidNestedBlocks"/>
<module name="EmptyBlock">
<property name="tokens"
value="LITERAL_WHILE, LITERAL_TRY, LITERAL_FINALLY, LITERAL_DO, LITERAL_IF,
LITERAL_ELSE, LITERAL_FOR, INSTANCE_INIT, STATIC_INIT, LITERAL_SWITCH,
LITERAL_SYNCHRONIZED"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="(ignore|expect)"/>
</module>
<module name="LeftCurly">
<property name="ignoreEnums" value="false"/>
<property name="tokens"
value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
OBJBLOCK, STATIC_INIT, RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="NeedBraces">
<property name="id" value="SingleLineIf"/>
<property name="tokens" value="LITERAL_IF"/>
<property name="allowSingleLineStatement" value="true"/>
</module>
<module name="NeedBraces">
<property name="id" value="NoSingleLineControl"/>
<property name="tokens" value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_WHILE"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF, LITERAL_SWITCH"/>
</module>
<!-- Class Design -->
<module name="DesignForExtension">
<property name="severity" value="info"/>
</module>
<module name="FinalClass"/>
<module name="HideUtilityClassConstructor"/>
<module name="InnerTypeLast"/>
<module name="InterfaceIsType"/>
<module name="MutableException"/>
<module name="OneTopLevelClass"/>
<module name="ThrowsCount">
<property name="max" value="0"/>
</module>
<module name="VisibilityModifier">
<property name="protectedAllowed" value="true"/>
</module>
<!-- Coding -->
<module name="ArrayTrailingComma"/>
<module name="AvoidDoubleBraceInitialization"/>
<module name="AvoidNoArgumentSuperConstructorCall"/>
<module name="CovariantEquals"/>
<module name="DeclarationOrder">
<!-- Doesn't respect static methods at top -->
<property name="severity" value="ignore"/>
</module>
<module name="DefaultComesLast"/>
<module name="EmptyStatement"/>
<module name="EqualsAvoidNull"/>
<module name="EqualsHashCode"/>
<module name="FallThrough">
<property name="checkLastCaseGroup" value="true"/>
</module>
<module name="HiddenField">
<property name="ignoreConstructorParameter" value="true"/>
<property name="ignoreSetter" value="true"/>
<property name="setterCanReturnItsClass" value="true"/>
<property name="ignoreAbstractMethods" value="true"/>
<!-- Not smart enough -->
<property name="severity" value="ignore"/>
</module>
<module name="IllegalCatch"/>
<module name="IllegalThrows"/>
<module name="IllegalToken"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="IllegalType"/>
<module name="InnerAssignment"/>
<module name="MagicNumber">
<property name="ignoreHashCodeMethod" value="true"/>
<property name="ignoreAnnotationElementDefaults" value="true"/>
</module>
<module name="MissingSwitchDefault"/>
<module name="ModifiedControlVariable"/>
<module name="MultipleStringLiterals">
</module>
<module name="MultipleVariableDeclarations"/>
<module name="NestedForDepth">
<module name="LineLength">
<property name="max" value="160"/>
<property name="severity" value="warning"/>
</module>
<module name="NestedIfDepth"/>
<module name="NestedTryDepth"/>
<module name="NoClone"/>
<module name="NoFinalizer"/>
<module name="OneStatementPerLine"/>
<module name="PackageDeclaration"/>
<module name="ParameterAssignment"/>
<module name="RequireThis"/>
<module name="ReturnCount">
<property name="severity" value="info"/>
</module>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<module name="StringLiteralEquality"/>
<module name="SuperClone"/>
<module name="SuperFinalize"/>
<module name="UnnecessaryParentheses"/>
<module name="UnnecessarySemicolonAfterOuterTypeDeclaration"/>
<module name="UnnecessarySemicolonAfterTypeMemberDeclaration"/>
<module name="UnnecessarySemicolonInEnumeration"/>
<module name="UnnecessarySemicolonInTryWithResources"/>
<module name="UnusedLocalVariable"/>
<module name="VariableDeclarationUsageDistance">
<property name="allowedDistance" value="3"/>
<property name="validateBetweenScopes" value="false"/>
</module>
<module name="VariableDeclarationUsageDistance">
<property name="allowedDistance" value="5"/>
<property name="validateBetweenScopes" value="true"/>
</module>
<!-- Imports -->
<module name="AvoidStarImport"/>
<module name="IllegalImport">
<property name="illegalPkgs" value="sun"/>
</module>
<module name="ImportOrder">
<property name="option" value="bottom"/>
<property name="ordered" value="true"/>
<property name="separated" value="true"/>
<property name="separatedStaticGroups" value="true"/>
<property name="caseSensitive" value="true"/>
<property name="sortStaticImportsAlphabetically" value="true"/>
<property name="groups"
value="java,javax,*,org.mvplugins"/>
<property name="staticGroups"
value="/^.*$/"/>
</module>
<module name="RedundantImport"/>
<module name="UnusedImports"/>
<!-- Javadoc Comments -->
<module name="AtclauseOrder">
<property name="target"
value="CLASS_DEF, COMPACT_CTOR_DEF, CTOR_DEF, ENUM_DEF,
INTERFACE_DEF, METHOD_DEF, RECORD_DEF, VARIABLE_DEF"/>
</module>
<module name="InvalidJavadocPosition"/>
<module name="JavadocBlockTagLocation"/>
<module name="JavadocContentLocationCheck"/>
<module name="JavadocMethod">
<property name="accessModifiers" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/>
<property name="scope" value="package"/><!-- We don't need javadoc for private methods -->
<property name="tokens" value="METHOD_DEF"/><!-- We don't need javadoc for constructors -->
</module>
<module name="JavadocMethod">
<property name="accessModifiers" value="public"/>
</module>
<module name="JavadocMissingLeadingAsterisk"/>
<module name="JavadocMissingWhitespaceAfterAsterisk"/>
<module name="JavadocParagraph">
<property name="allowNewlineParagraph" value="true"/>
</module>
<module name="JavadocStyle">
<property name="scope" value="package"/>
</module>
<module name="JavadocTagContinuationIndentation"/>
<module name="JavadocType"/>
<module name="JavadocVariable">
<property name="scope" value="package"/>
</module>
<module name="MissingJavadocMethod">
<property name="scope" value="public"/>
<property name="allowMissingPropertyJavadoc" value="true"/>
</module>
<module name="MissingJavadocMethod">
<property name="scope" value="protected"/>
<property name="excludeScope" value="public"/>
<property name="allowMissingPropertyJavadoc" value="true"/>
<property name="minLineCount" value="2"/>
</module>
<module name="MissingJavadocType">
<property name="scope" value="protected"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
RECORD_DEF, ANNOTATION_DEF"/>
<property name="excludeScope" value="nothing"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="RequireEmptyLineBeforeBlockTagGroup"/>
<module name="SingleLineJavadoc"/>
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
<property name="scope" value="package"/><!-- We don't need javadoc for private variables -->
</module>
<module name="JavadocStyle"/>
<module name="WriteTag">
<property name="tag" value="@author"/>
<property name="tagFormat" value="\S"/>
<property name="severity" value="ignore"/>
<property name="tagSeverity" value="warning"/>
</module>
<!-- Metrics -->
<module name="BooleanExpressionComplexity"/>
<module name="ClassDataAbstractionCoupling">
<property name="max" value="7"/>
<property name="excludedClasses"
value="ArrayIndexOutOfBoundsException, ArrayList, Boolean, Byte, Character,
Class, Collection, Deprecated, Deque, Double, DoubleStream, EnumSet, Exception,
Float, FunctionalInterface, HashMap, HashSet, IllegalArgumentException,
IllegalStateException, IndexOutOfBoundsException, IntStream, Integer,
LinkedHashMap, LinkedHashSet, LinkedList, List, Long, LongStream, Map,
NullPointerException, Object, Optional, OptionalDouble, OptionalInt,
OptionalLong, Override, Queue, RuntimeException, SafeVarargs, SecurityException,
Set, Short, SortedMap, SortedSet, Stream, String, StringBuffer, StringBuilder,
SuppressWarnings, Throwable, TreeMap, TreeSet, UnsupportedOperationException,
Void, boolean, byte, char, double, float, int, long, short, var, void"/>
</module>
<module name="ClassFanOutComplexity">
<property name="id" value="FanOutComplexityGettingTooHigh"/>
<property name="max" value="20"/>
<property name="excludedClasses"
value="ArrayIndexOutOfBoundsException, ArrayList, Boolean, Byte, Character,
Class, Collection, Deprecated, Deque, Double, DoubleStream, EnumSet, Exception,
Float, FunctionalInterface, HashMap, HashSet, IllegalArgumentException,
IllegalStateException, IndexOutOfBoundsException, IntStream, Integer,
LinkedHashMap, LinkedHashSet, LinkedList, List, Long, LongStream, Map,
NullPointerException, Object, Optional, OptionalDouble, OptionalInt,
OptionalLong, Override, Queue, RuntimeException, SafeVarargs, SecurityException,
Set, Short, SortedMap, SortedSet, Stream, String, StringBuffer, StringBuilder,
SuppressWarnings, Throwable, TreeMap, TreeSet, UnsupportedOperationException,
Void, boolean, byte, char, double, float, int, long, short, var, void"/>
<property name="severity" value="info"/>
</module>
<module name="ClassFanOutComplexity">
<property name="id" value="FanOutComplexityProbablyTooHigh"/>
<property name="max" value="35"/>
<property name="excludedClasses"
value="ArrayIndexOutOfBoundsException, ArrayList, Boolean, Byte, Character,
Class, Collection, Deprecated, Deque, Double, DoubleStream, EnumSet, Exception,
Float, FunctionalInterface, HashMap, HashSet, IllegalArgumentException,
IllegalStateException, IndexOutOfBoundsException, IntStream, Integer,
LinkedHashMap, LinkedHashSet, LinkedList, List, Long, LongStream, Map,
NullPointerException, Object, Optional, OptionalDouble, OptionalInt,
OptionalLong, Override, Queue, RuntimeException, SafeVarargs, SecurityException,
Set, Short, SortedMap, SortedSet, Stream, String, StringBuffer, StringBuilder,
SuppressWarnings, Throwable, TreeMap, TreeSet, UnsupportedOperationException,
Void, boolean, byte, char, double, float, int, long, short, var, void"/>
</module>
<module name="CyclomaticComplexity">
<property name="max" value="7"/>
<module name="ConstantName"/>
<module name="LocalVariableName"/>
<module name="MemberName"/>
<module name="MethodName"/>
<module name="PackageName"/>
<module name="ParameterName"/>
<module name="StaticVariableName"/>
<module name="TypeName"/>
<module name="AvoidStarImport">
<property name="severity" value="warning"/>
<property name="excludes" value="com.onarandombox.MultiverseCore.utils,com.onarandombox.MultiverseCore.configuration,com.onarandombox.MultiverseCore.commandsold,com.onarandombox.MultiverseCore.destination"/>
</module>
<module name="JavaNCSS">
<property name="methodMaximum" value="50"/>
<property name="classMaximum" value="1500"/>
<property name="fileMaximum" value="2000"/>
<property name="recordMaximum" value="150"/>
</module>
<module name="NPathComplexity">
<property name="max" value="200"/>
</module>
<!-- Miscellaneous -->
<module name="ArrayTypeStyle"/>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="CommentsIndentation">
<property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN"/>
</module>
<module name="Indentation">
<property name="basicOffset" value="4"/>
<property name="braceAdjustment" value="4"/>
<property name="caseIndent" value="4"/>
<property name="throwsIndent" value="8"/>
<property name="arrayInitIndent" value="4"/>
<property name="lineWrappingIndentation" value="8"/>
<property name="forceStrictCondition" value="true"/>
</module>
<module name="NoCodeInFile"/>
<module name="OuterTypeFilename"/>
<module name="TodoComment">
<property name="format" value="TODO"/>
<!-- TODO change back to warning after MV5 -->
<property name="severity" value="info"/>
</module>
<module name="TrailingComment">
<property name="legalComment" value="^\sSUPPRESS CHECKSTYLE:"/>
</module>
<module name="UncommentedMain"/>
<module name="UpperEll"/>
<!-- Modifiers -->
<module name="ModifierOrder"/>
<module name="RedundantModifier"/>
<!-- Naming Conventions -->
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="0"/>
<property name="allowedAbbreviations" value="MV"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF,
RECORD_COMPONENT_DEF"/>
</module>
<module name="AbstractClassName">
<property name="ignoreName" value="true"/>
<message key="name.invalidPattern"
value="Abstract class name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="^[A-Z]{1,3}$"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ConstantName">
<message key="name.invalidPattern"
value="Constant name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="^[A-Z]{1,3}$"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalFinalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local final variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$|^[A-Z][A-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodName">
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="^[A-Z]{1,3}$"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="PackageName">
<property name="severity" value="info"/>
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="PatternVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Pattern variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordComponentName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Record component name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordTypeParameterName">
<property name="format" value="^[A-Z]{1,3}$"/>
<message key="name.invalidPattern"
value="Record type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="StaticVariableName">
<message key="name.invalidPattern"
value="Static variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
ANNOTATION_DEF, RECORD_DEF"/>
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<!-- Size Violations -->
<module name="AnonInnerLength">
<property name="max" value="20"/>
</module>
<module name="ExecutableStatementCount">
<property name="max" value="30"/>
</module>
<module name="LambdaBodyLength">
<property name="id" value="LambdaGettingTooLong"/>
<property name="max" value="10"/>
<property name="severity" value="info"/>
</module>
<module name="LambdaBodyLength">
<property name="id" value="LambdaProbablyTooLong"/>
<property name="max" value="25"/>
</module>
<module name="MethodCount">
<property name="maxTotal" value="100"/>
<property name="maxPrivate" value="100"/>
<property name="maxPackage" value="100"/>
<property name="maxProtected" value="100"/>
<property name="maxPublic" value="100"/>
<module name="IllegalImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports">
<property name="processJavadoc" value="true"/>
</module>
<module name="MethodLength">
<property name="max" value="50"/>
<property name="severity" value="warning"/>
<property name="countEmpty" value="false"/>
</module>
<module name="OuterTypeNumber">
<property name="max" value="1"/>
</module>
<module name="ParameterNumber">
<property name="id" value="ConsiderLessMethodParameters"/>
<property name="max" value="4"/>
<property name="ignoreOverriddenMethods" value="true"/>
<property name="severity" value="info"/>
<property name="tokens" value="METHOD_DEF"/>
</module>
<module name="ParameterNumber">
<property name="id" value="ProbablyTooManyMethodParameters"/>
<property name="max" value="10"/>
<property name="ignoreOverriddenMethods" value="true"/>
<property name="tokens" value="METHOD_DEF"/>
</module>
<module name="ParameterNumber">
<property name="id" value="ConsiderLessConstructorParameters"/>
<property name="max" value="7"/>
<property name="ignoreOverriddenMethods" value="true"/>
<property name="severity" value="info"/>
<property name="tokens" value="CTOR_DEF"/>
</module>
<module name="ParameterNumber">
<property name="id" value="ProbablyTooManyConstructorParameters"/>
<property name="max" value="12"/>
<property name="ignoreOverriddenMethods" value="true"/>
<property name="tokens" value="CTOR_DEF"/>
</module>
<module name="RecordComponentNumber">
<property name="max" value="8"/>
</module>
<!-- Whitespace -->
<module name="EmptyForInitializerPad"/>
<module name="ParameterNumber"/>
<module name="EmptyForIteratorPad"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
<property name="allowMultipleEmptyLines" value="false"/>
<property name="allowMultipleEmptyLinesInsideClassMembers" value="false"/>
<property name="tokens"
value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/>
</module>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="MethodParamPad">
<property name="tokens"
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
SUPER_CTOR_CALL, ENUM_CONSTANT_DEF, RECORD_DEF"/>
</module>
<module name="NoLineWrap">
<property name="tokens" value="PACKAGE_DEF, IMPORT, STATIC_IMPORT"/>
</module>
<module name="MethodParamPad"/>
<module name="NoWhitespaceAfter">
<property name="tokens"
value="AT, INC, DEC, UNARY_MINUS,UNARY_PLUS,BNOT,LNOT,DOT,ARRAY_DECLARATOR,INDEX_OP,LITERAL_SYNCHRONIZED,METHOD_REF"/>
<property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS"/>
</module>
<module name="NoWhitespaceBefore">
<property name="id" value="AllowedWhitespaceBeforeWithoutLinebreak"/>
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, ELLIPSIS, LABELED_STAT"/>
</module>
<module name="NoWhitespaceBefore">
<property name="id" value="AllowedWhitespaceBeforeWithLinebreak"/>
<property name="tokens" value="DOT, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="NoWhitespaceBeforeCaseDefaultColon"/>
<module name="OperatorWrap">
<property name="tokens"
value="QUESTION, COLON, EQUAL, NOT_EQUAL, DIV, PLUS, MINUS, STAR, MOD,
SR, BSR, GE, GT, SL, LE, LT, BXOR, BOR, LOR, BAND, LAND, LITERAL_INSTANCEOF,
TYPE_EXTENSION_AND, ASSIGN, DIV_ASSIGN, PLUS_ASSIGN, MINUS_ASSIGN,
STAR_ASSIGN, MOD_ASSIGN, SR_ASSIGN, BSR_ASSIGN, SL_ASSIGN, BXOR_ASSIGN,
BOR_ASSIGN, BAND_ASSIGN, METHOD_REF"/>
</module>
<module name="ParenPad">
<property name="tokens"
value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA,
RECORD_DEF"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapNl"/>
<property name="option" value="nl"/>
<property name="tokens" value="DOT, AT, METHOD_REF"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapEol"/>
<property name="option" value="eol"/>
<property name="tokens"
value="COMMA, SEMI, ELLIPSIS, RPAREN, ARRAY_DECLARATOR, RBRACK"/>
</module>
<module name="SingleSpaceSeparator"/>
<module name="NoWhitespaceBefore"/>
<module name="OperatorWrap"/>
<module name="ParenPad"/>
<module name="TypecastParenPad"/>
<module name="WhitespaceAfter">
<property name="tokens"
value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE, LITERAL_RETURN,
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, LITERAL_FINALLY, DO_WHILE, ELLIPSIS,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_CATCH, LAMBDA,
LITERAL_YIELD, LITERAL_CASE"/>
<property name="severity" value="warning"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyLambdas" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<property name="ignoreEnhancedForColon" value="false"/>
<property name="tokens"
value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks
may only be represented as '{}' when not part of a multi-block statement"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
<property name="severity" value="warning"/>
</module>
<module name="ModifierOrder"/>
<module name="RedundantModifier"/>
<module name="AvoidNestedBlocks"/>
<module name="EmptyBlock">
<property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_FOR,LITERAL_TRY,LITERAL_WHILE,INSTANCE_INIT,STATIC_INIT"/>
</module>
<module name="LeftCurly"/>
<module name="RightCurly"/>
<module name="EmptyStatement"/>
<module name="EqualsHashCode"/>
<module name="HiddenField">
<property name="tokens" value="VARIABLE_DEF"/><!-- We don't care if parameters hide fields. -->
</module>
<module name="IllegalInstantiation"/>
<module name="InnerAssignment"/>
<module name="MagicNumber">
<property name="ignoreNumbers" value="-1, 0, 0.5, 1, 2, 3"/>
</module>
<module name="MissingSwitchDefault"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<!-- Don't like errors for `final` missing
<module name="DesignForExtension"/>
<module name="FinalClass"/>
-->
<module name="HideUtilityClassConstructor"/>
<module name="InterfaceIsType"/>
<module name="VisibilityModifier">
<property name="protectedAllowed" value="true"/>
</module>
<module name="ArrayTypeStyle"/>
<!-- Don't like errors for `final` missing
<module name="FinalParameters"/>
-->
<module name="TodoComment">
<property name="severity" value="info"/>
</module>
<module name="UpperEll"/>
<module name="Indentation"/>
<module name="MissingDeprecated"/>
<module name="MissingOverride"/>
</module>
</module>
-6
View File
@@ -2,10 +2,4 @@
* This file was generated by the Gradle 'init' task.
*/
pluginManagement {
repositories {
gradlePluginPortal()
}
}
rootProject.name = 'multiverse-core'
@@ -5,20 +5,38 @@
* with this project. *
******************************************************************************/
package org.mvplugins.multiverse.core;
package com.onarandombox.MultiverseCore;
import java.io.File;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.anchor.AnchorManager;
import com.onarandombox.MultiverseCore.api.Destination;
import com.onarandombox.MultiverseCore.api.MVCore;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.PluginLocales;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
import com.onarandombox.MultiverseCore.economy.MVEconomist;
import com.onarandombox.MultiverseCore.inject.InjectableListener;
import com.onarandombox.MultiverseCore.inject.PluginInjection;
import com.onarandombox.MultiverseCore.placeholders.MultiverseCorePlaceholders;
import com.onarandombox.MultiverseCore.utils.TestingMode;
import com.onarandombox.MultiverseCore.utils.metrics.MetricsConfigurator;
import com.onarandombox.MultiverseCore.world.WorldProperties;
import io.vavr.control.Try;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import me.main__.util.SerializationConfig.SerializationConfig;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader;
@@ -29,24 +47,6 @@ 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.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.economy.MVEconomist;
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.config.NullLocation;
import org.mvplugins.multiverse.core.world.config.SpawnLocation;
/**
* The implementation of the Multiverse-{@link MVCore}.
*/
@@ -56,9 +56,9 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
private ServiceLocator serviceLocator;
@Inject
private Provider<MVCoreConfig> configProvider;
private MVCoreConfig config;
@Inject
private Provider<WorldManager> worldManagerProvider;
private Provider<MVWorldManager> worldManagerProvider;
@Inject
private Provider<AnchorManager> anchorManagerProvider;
@Inject
@@ -84,20 +84,15 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
@Override
public void onLoad() {
// Create our DataFolder
getDataFolder().mkdirs();
// Setup our Logging
Logging.init(this);
// Create our DataFolder
if (!getDataFolder().exists() && !getDataFolder().mkdirs()) {
Logging.severe("Failed to create data folder!");
getServer().getPluginManager().disablePlugin(this);
return;
}
// Register our config classes
SerializationConfig.registerAll(WorldProperties.class);
SerializationConfig.initLogging(Logging.getLogger());
ConfigurationSerialization.registerClass(NullLocation.class);
ConfigurationSerialization.registerClass(SpawnLocation.class);
}
/**
@@ -108,35 +103,42 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
initializeDependencyInjection();
// Load our configs first as we need them for everything else.
var config = configProvider.get();
if (!config.isLoaded()) {
if (config == null || !config.isLoaded()) {
Logging.severe("Your configs were not loaded.");
Logging.severe("Please check your configs and restart the server.");
this.getServer().getPluginManager().disablePlugin(this);
return;
}
Logging.setShowingConfig(shouldShowConfig());
// Initialize the worlds
worldManagerProvider.get().initAllWorlds().andThenTry(() -> {
// Setup economy here so vault is loaded
loadEconomist();
var worldManager = worldManagerProvider.get();
// Init all the other stuff
loadAnchors();
registerEvents();
setUpLocales();
registerCommands();
registerDestinations();
setupMetrics();
loadPlaceholderApiIntegration();
saveAllConfigs();
logEnableMessage();
}).onFailure(e -> {
Logging.severe("Failed to multiverse core! Disabling...");
e.printStackTrace();
getServer().getPluginManager().disablePlugin(this);
});
worldManager.loadWorldsConfig();
worldManager.getDefaultWorldGenerators();
worldManager.loadDefaultWorlds();
worldManager.loadWorlds(true);
// Now set the firstspawnworld (after the worlds are loaded):
worldManager.setFirstSpawnWorld(config.getFirstSpawnLocation());
MVWorld firstSpawnWorld = worldManager.getFirstSpawnWorld();
if (firstSpawnWorld != null) {
config.setFirstSpawnLocation(firstSpawnWorld.getName());
}
//Setup economy here so vault is loaded
this.loadEconomist();
// Init all the other stuff
this.loadAnchors();
this.registerEvents();
this.setUpLocales();
this.registerCommands();
this.registerDestinations();
this.setupMetrics();
this.loadPlaceholderAPIIntegration();
this.saveAllConfigs();
this.logEnableMessage();
}
/**
@@ -144,7 +146,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
*/
@Override
public void onDisable() {
saveAllConfigs();
this.saveAllConfigs();
shutdownDependencyInjection();
Logging.shutdown();
}
@@ -169,7 +171,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
}
private boolean shouldShowConfig() {
return !configProvider.get().getSilentStart();
return !config.getSilentStart();
}
private void loadEconomist() {
@@ -195,8 +197,8 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
private void registerEvents() {
var pluginManager = getServer().getPluginManager();
Try.run(() -> serviceLocator.getAllServices(InjectableListener.class).forEach(
listener -> pluginManager.registerEvents(listener, this)))
Try.run(() -> serviceLocator.getAllServices(InjectableListener.class)
.forEach(listener -> pluginManager.registerEvents(listener, this)))
.onFailure(e -> {
throw new RuntimeException("Failed to register listeners. Terminating...", e);
});
@@ -218,7 +220,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
}
/**
* Register locales.
* Register locales
*/
private void setUpLocales() {
Try.of(() -> commandManagerProvider.get())
@@ -273,14 +275,14 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
private void logEnableMessage() {
Logging.config("Version %s (API v%s) Enabled - By %s", this.getDescription().getVersion(), PROTOCOL, getAuthors());
if (configProvider.get().isShowingDonateMessage()) {
if (config.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()
private void loadPlaceholderAPIIntegration() {
if (config.isRegisterPapiHook()
&& getServer().getPluginManager().getPlugin("PlaceholderAPI") != null) {
Try.run(() -> serviceLocator.createAndInitialize(MultiverseCorePlaceholders.class))
.onFailure(e -> {
@@ -312,7 +314,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
@Override
public String getAuthors() {
List<String> authorsList = this.getDescription().getAuthors();
if (authorsList.isEmpty()) {
if (authorsList.size() == 0) {
return "";
}
@@ -365,18 +367,17 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
*/
@Override
public boolean saveAllConfigs() {
// TODO: Make this all Try<Void>
return configProvider.get().save().isSuccess()
return config.save()
&& 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
* @param qualifiers The set of qualifiers that must match this service definition
* @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
*/
@@ -394,16 +395,16 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
* 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
* @param qualifiers The set of qualifiers that must match this service definition
* @return A list of services implementing this contract or concrete implementation. May not return null, but may
* return an empty list.
* 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 {
Annotation... qualifiers
) throws MultiException {
var handles = serviceLocator.getAllServiceHandles(contractOrImpl, qualifiers);
return handles.stream()
.filter(ServiceHandle::isActive)
@@ -414,10 +415,10 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
/**
* This is for unit testing ONLY. Do not use this constructor.
*
* @param loader The PluginLoader to use.
* @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.
* @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,11 +1,10 @@
package org.mvplugins.multiverse.core;
package com.onarandombox.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVCore;
import com.onarandombox.MultiverseCore.inject.binder.JavaPluginBinder;
import org.glassfish.hk2.utilities.binding.ScopedBindingBuilder;
import org.jetbrains.annotations.NotNull;
import org.mvplugins.multiverse.core.api.MVCore;
import org.mvplugins.multiverse.core.inject.binder.JavaPluginBinder;
class MultiverseCorePluginBinder extends JavaPluginBinder<MultiverseCore> {
protected MultiverseCorePluginBinder(@NotNull MultiverseCore plugin) {
@@ -13,8 +12,7 @@ class MultiverseCorePluginBinder extends JavaPluginBinder<MultiverseCore> {
}
@Override
protected ScopedBindingBuilder<MultiverseCore> bindPluginClass(
ScopedBindingBuilder<MultiverseCore> bindingBuilder) {
protected ScopedBindingBuilder<MultiverseCore> bindPluginClass(ScopedBindingBuilder<MultiverseCore> bindingBuilder) {
return super.bindPluginClass(bindingBuilder).to(MVCore.class).to(MultiverseCore.class);
}
}
@@ -5,17 +5,12 @@
* with this project. *
******************************************************************************/
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.HashSet;
import java.util.Map;
import java.util.Set;
package com.onarandombox.MultiverseCore.anchor;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.LocationManipulation;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import jakarta.inject.Inject;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
@@ -25,9 +20,13 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.MultiverseCore;
import org.mvplugins.multiverse.core.api.LocationManipulation;
import org.mvplugins.multiverse.core.config.MVCoreConfig;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Manages anchors.
@@ -1,4 +1,4 @@
/**
* this package contains the classes that are used for the anchor system.
*/
package org.mvplugins.multiverse.core.anchor;
package com.onarandombox.MultiverseCore.anchor;
@@ -1,10 +1,9 @@
package org.mvplugins.multiverse.core.api;
package com.onarandombox.MultiverseCore.api;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Vehicle;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Contract;
/**
@@ -38,35 +37,8 @@ public interface BlockSafety {
*/
boolean playerCanSpawnHereSafely(Location l);
/**
* Finds a portal-block next to the specified {@link Location}.
*
* @param location The {@link Location}
* @return The next portal-block's {@link Location}.
*/
Location findPortalBlockNextTo(Location location);
/**
* Gets the next safe location around the given location.
*
* @param location A {@link Location}.
* @return A safe {@link Location}.
*/
@Nullable Location getSafeLocation(Location location);
/**
* Gets the next safe location around the given location.
*
* @param location A {@link Location}.
* @param tolerance The tolerance of how far up and down to search.
* @param radius The radius around given location to search.
* @return A safe {@link Location}.
*/
@Nullable Location getSafeLocation(Location location, int tolerance, int radius);
/**
* 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.
*/
@@ -74,7 +46,6 @@ public interface BlockSafety {
/**
* 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.
*/
@@ -82,7 +53,6 @@ public interface BlockSafety {
/**
* 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.
*/
@@ -90,7 +60,6 @@ public interface BlockSafety {
/**
* 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}.
*/
@@ -98,7 +67,6 @@ public interface BlockSafety {
/**
* Checks if the specified {@link Minecart} can spawn safely.
*
* @param cart The {@link Minecart}.
* @return True if the minecart can spawn safely.
*/
@@ -106,7 +74,6 @@ public interface BlockSafety {
/**
* Checks if the specified {@link Vehicle} can spawn safely.
*
* @param vehicle The {@link Vehicle}.
* @return True if the vehicle can spawn safely.
*/
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.api;
package com.onarandombox.MultiverseCore.api;
import java.util.Collection;
@@ -45,4 +45,14 @@ public interface Destination<T extends DestinationInstance> {
* @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();
}
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.api;
package com.onarandombox.MultiverseCore.api;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.api;
package com.onarandombox.MultiverseCore.api;
import org.bukkit.Location;
import org.bukkit.entity.Vehicle;
@@ -1,11 +1,10 @@
package org.mvplugins.multiverse.core.api;
package com.onarandombox.MultiverseCore.api;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import com.onarandombox.MultiverseCore.placeholders.MultiverseCorePlaceholders;
import io.vavr.control.Try;
import org.jvnet.hk2.annotations.Contract;
import org.mvplugins.multiverse.core.configuration.handle.StringPropertyHandle;
import org.mvplugins.multiverse.core.placeholders.MultiverseCorePlaceholders;
@Contract
public interface MVConfig {
@@ -13,7 +12,7 @@ public interface MVConfig {
* Loads the config from disk.
* @return True if the config was loaded successfully.
*/
Try<Void> load();
boolean load();
/**
* Whether the config has been loaded.
@@ -24,14 +23,33 @@ public interface MVConfig {
/**
* Saves the config to disk.
*/
Try<Void> save();
boolean save();
/**
* Gets the handler for managing config with string names and values.
* Gets the nodes for the config.
*
* @return The config handle for string properties.
* @return The nodes for the config.
*/
StringPropertyHandle getStringPropertyHandle();
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.
@@ -107,30 +125,6 @@ public interface MVConfig {
*/
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.
*
@@ -5,7 +5,7 @@
* with this project. *
******************************************************************************/
package org.mvplugins.multiverse.core.api;
package com.onarandombox.MultiverseCore.api;
/**
* Multiverse 2 Core API
@@ -0,0 +1,142 @@
/******************************************************************************
* 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 com.onarandombox.MultiverseCore.api;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.Vector;
/**
* A destination API for Multiverse
* Any plugin can add these to MV and when they are, any action that uses them (portals, MVTP, etc.) can use them!
*/
@Deprecated
public interface MVDestination {
/**
* 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!
*
* @return The identifier or prefix that is required for this destination.
*/
String getIdentifier();
/**
* Allows you to determine if a Destination is valid for the type it thinks it is.
* <p>
* An example of this would be the exact destination. A valid string would be: e:0,0,0 where an invalid one would
* be e:1:2:3. The first string would return true the second would return false. This is simply a convenience
* method
* and does not even NEED to be called, but it's highly recommended if you're teleporting, but it's mainly for
* Multiverse Internal use.
*
* @param plugin The plugin who the type belongs to.
* @param destination The destination string. ex: p:MyPortal:nw
*
* @return True if the destination is valid, false if not.
*/
boolean isThisType(JavaPlugin plugin, String destination);
/**
* Returns the location a specific entity will spawn at when being teleported to this Destination.
* <p>
* To just retrieve the location as it is stored you can just pass null, but be warned some destinations may return
* null back to you if you do this. It is always safer to pass an actual entity. This is used so things like
* minecarts can be teleported.
* <p>
* Do not forget to use {@link #getVelocity()} as destinations can use this too!
*
* @param entity The entity to be teleported.
*
* @return The location of the entity.
*/
Location getLocation(Entity entity);
/**
* Returns the velocity vector for this destination.
* <p>
* Plugins wishing to fully support MVDestinations MUST implement this.
*
* @return A vector representing the speed/direction the player should travel when arriving
*/
Vector getVelocity();
/**
* Sets the destination string.
* <p>
* This should be used when you want to tell this destination object about a change in where it should take people.
* The destination param should be match the result from {@link #getIdentifier()}. A valid example would be that if
* {@link #getIdentifier()} returned "ow" our destination string could be "ow:TownCenter" but could not be
* "p:HomePortal"
*
* @param plugin The plugin who the type belongs to.
* @param destination The destination string. ex: p:MyPortal:nw
*/
void setDestination(JavaPlugin plugin, String destination);
/**
* Returns true if the destination is valid and players will be taken to it.
* <p>
* Even if destinations are in the correct format (p:MyPortal) MyPortal may not exist, and therefore this would
* return false.
*
* @return True if the destination is valid; false if not.
*/
boolean isValid();
/**
* Gives you a general friendly description of the type of destination.
* <p>
* For example, the PlayerDestination sets this to "Player". You can use this to show where a player will be taken.
*
* @return A friendly string description of the type of destination.
*/
String getType();
/**
* Gives you a specific name of the destination.
* <p>
* For example, the PlayerDestination sets this to The Player's Name.
*
* @return A friendly string stating the name of the destination.
*/
String getName();
/**
* Returns a string that can easily be saved in the config that contains all the details needed to rebuild this
* destination.
* <p>
* ex: e:0,0,0:50:50
*
* @return The savable config string.
*/
String toString();
/**
* Returns the permissions string required to go here.
* <p>
* ex: multiverse.access.world
* <p>
* NOTE: This is NOT the permission to use the teleport command.
*
* @return the permissions string required to go here.
*/
String getRequiredPermission();
/**
* Should the Multiverse SafeTeleporter be used?
* <p>
* If not, MV will blindly take people to the location specified.
*
* @return True if the SafeTeleporter will be used, false if not.
*/
boolean useSafeTeleporter();
}
@@ -5,7 +5,7 @@
* with this project. *
******************************************************************************/
package org.mvplugins.multiverse.core.api;
package com.onarandombox.MultiverseCore.api;
/**
* This interface is implemented by every official Multiverse-plugin.
@@ -14,7 +14,7 @@ public interface MVPlugin {
/**
* Gets the reference to MultiverseCore.
*
* @return A valid {@link org.mvplugins.multiverse.core.MultiverseCore}.
* @return A valid {@link com.onarandombox.MultiverseCore}.
*/
MVCore getCore();
@@ -0,0 +1,675 @@
/******************************************************************************
* 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 com.onarandombox.MultiverseCore.api;
import java.util.List;
import com.onarandombox.MultiverseCore.exceptions.PropertyDoesNotExistException;
import com.onarandombox.MultiverseCore.world.configuration.AddProperties;
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
import com.onarandombox.MultiverseCore.world.configuration.EnglishChatColor;
import org.bukkit.ChatColor;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.WorldType;
import org.bukkit.permissions.Permission;
import org.jetbrains.annotations.Nullable;
/**
* The API for a Multiverse Handled World.
*/
public interface MVWorld {
/**
* Returns the Bukkit world object that this world describes.
*
* @return A {@link World}
*/
World getCBWorld();
/**
* Gets the name of this world. The name cannot be changed.
* <p>
* Note for plugin developers: Usually {@link #getAlias()}
* is what you want to use instead of this method.
*
* @return The name of the world as a String.
*/
String getName();
/**
* Gets the type of this world. As of 1.2 this will be:
* FLAT, NORMAL or VERSION_1_1
* <p>
* This is <b>not</b> the generator.
*
* @return The Type of this world.
*/
WorldType getWorldType();
/**
* Gets the environment of this world.
*
* @return A {@link org.bukkit.World.Environment}.
*/
World.Environment getEnvironment();
/**
* Sets the environment of a world.
* <p>
* Note: This will ONLY take effect once the world is unloaded/reloaded.
*
* @param environment A {@link org.bukkit.World.Environment}.
*/
void setEnvironment(World.Environment environment);
/**
* Gets the difficulty of this world.
*
* @return The difficulty of this world.
*/
Difficulty getDifficulty();
/**
* Sets the difficulty of this world and returns true if success.
* Valid string values are either an integer of difficulty(0-3) or
* the name that resides in the Bukkit enum, ex. {@code PEACEFUL}
*
* @param difficulty The difficulty to set the world to as a string.
* @return True if success, false if the provided string
* could not be translated to a difficulty.
* @deprecated Use {@link #setDifficulty(Difficulty)} or, if you have to
* pass a string, use {@link #setPropertyValue(String, String)} instead.
*/
@Deprecated
boolean setDifficulty(String difficulty);
/**
* Sets the difficulty of this world and returns {@code true} on success.
* Valid string values are either an integer of difficulty(0-3) or
* the name that resides in the Bukkit enum, ex. PEACEFUL
*
* @param difficulty The new difficulty.
* @return True if success, false if the operation failed... for whatever reason.
*/
boolean setDifficulty(Difficulty difficulty);
/**
* Gets the world seed of this world.
*
* @return The Long version of the seed.
*/
long getSeed();
/**
* Sets the seed of this world.
*
* @param seed A Long that is the seed.
*/
void setSeed(long seed);
/**
* Gets the generator of this world.
*
* @return The name of the generator.
*/
String getGenerator();
/**
* Sets the generator of this world.
*
* @param generator The new generator's name.
*/
void setGenerator(String generator);
/**
* Gets the help-message for a property.
* @param property The name of the property.
* @return The help-message.
* @throws PropertyDoesNotExistException Thrown if the property was not found.
*/
String getPropertyHelp(String property) throws PropertyDoesNotExistException;
/**
* Gets a property as {@link String}.
*
* @param property The name of a world property to get.
* @return The string-representation of that property.
* @throws PropertyDoesNotExistException Thrown if the property was not found in the world.
*/
String getPropertyValue(String property) throws PropertyDoesNotExistException;
/**
* Sets a property to a given value.
*
* @param property The name of a world property to set.
* @param value A value in string representation, it will be parsed to the correct type.
* @return True if the value was set, false if not.
* @throws PropertyDoesNotExistException Thrown if the property was not found in the world.
*/
boolean setPropertyValue(String property, String value) throws PropertyDoesNotExistException;
/**
* Adds a value to the given property. The property must be a {@link AddProperties}.
*
* @param property The name of a {@link AddProperties} to add a value to.
* @param value A value in string representation, it will be parsed to the correct type.
* @return True if the value was added, false if not.
* @deprecated We changed the entire world-config-system. This is not compatible any more.
*/
@Deprecated
boolean addToVariable(String property, String value);
/**
* Removes a value from the given property. The property must be a {@link AddProperties}.
*
* @param property The name of a {@link AddProperties} to remove a value
* from.
* @param value A value in string representation, it will be parsed to the correct type.
* @return True if the value was removed, false if not.
* @deprecated We changed the entire world-config-system. This is not compatible any more.
*/
@Deprecated
boolean removeFromVariable(String property, String value);
/**
* Removes all values from the given property. The property must be a {@link AddProperties}.
*
* @param property The name of a {@link AddProperties} to clear.
* @return True if it was cleared, false if not.
* @deprecated We changed the entire world-config-system. This is not compatible any more.
*/
@Deprecated
boolean clearVariable(String property);
/**
* Clears a list property (sets it to []).
*
* @param property The property to clear.
* @return True if success, false if fail.
* @deprecated We changed the entire world-config-system. This is not compatible any more.
*/
@Deprecated
boolean clearList(String property);
// end of old config stuff
// permission stuff
/**
* Gets the lowercased name of the world. This method is required, since the permissables
* lowercase all permissions when recalculating.
* <p>
* Note: This also means if a user has worlds named: world and WORLD, that they can both
* exist, and both be teleported to independently, but their permissions **cannot** be
* uniqueified at this time. See bug report #.
*
* @return The lowercased name of the world.
*/
String getPermissibleName();
/**
* Gets the permission required to enter this world.
*
* @return The permission required to be exempt from charges to/from this world.
*/
Permission getAccessPermission();
/**
* Gets the permission required to be exempt when entering.
*
* @return The permission required to be exempt when entering.
*/
Permission getExemptPermission();
// end of permission stuff
/**
* Gets the alias of this world.
* <p>
* This alias allows users to have a world named "world" but show up in the list as "FernIsland"
*
* @return The alias of the world as a String.
*/
String getAlias();
/**
* Sets the alias of the world.
*
* @param alias A string that is the new alias.
*/
void setAlias(String alias);
/**
* Gets the color that this world's name/alias will display as.
*
* @return The color of this world.
*/
ChatColor getColor();
/**
* Sets the color that this world's name/alias will display as.
*
* @param color A valid color name.
* @return True if the color was set, false if not.
*/
boolean setColor(String color);
/**
* Gets the style that this world's name/alias will display as.
*
* @return The style of this world. {@code null} for "normal" style.
*/
ChatColor getStyle();
/**
* Sets the style that this world's name/alias will display as.
*
* @param style A valid style name.
* @return True if the style was set, false if not.
*/
boolean setStyle(String style);
/**
* Tells you if someone entered a valid color.
*
* @param color A string that may translate to a color.
* @return True if it is a color, false if not.
*
* @deprecated This has been moved: {@link EnglishChatColor#isValidAliasColor(String)}
*/
@Deprecated
boolean isValidAliasColor(String color);
/**
* Returns a very nicely colored string (using Alias and Color if they are set).
*
* @return A nicely colored string.
*/
String getColoredWorldString();
// animals&monster stuff
/**
* Gets whether or not animals are allowed to spawn in this world.
*
* @return True if ANY animal can, false if no animals can spawn.
*/
boolean canAnimalsSpawn();
/**
* Sets whether or not animals can spawn.
* If there are values in {@link #getAnimalList()} and this is false,
* those animals become the exceptions, and will spawn
*
* @param allowAnimalSpawn True to allow spawning of monsters, false to prevent.
*/
void setAllowAnimalSpawn(boolean allowAnimalSpawn);
/**
* Returns a list of animals. This list always negates the {@link #canAnimalsSpawn()} result.
*
* @return A list of animals that will spawn if {@link #canAnimalsSpawn()} is false.
*/
List<String> getAnimalList();
/**
* Gets whether or not monsters are allowed to spawn in this world.
*
* @return True if ANY monster can, false if no monsters can spawn.
*/
boolean canMonstersSpawn();
/**
* Sets whether or not monsters can spawn.
* If there are values in {@link #getMonsterList()} and this is false,
* those monsters become the exceptions, and will spawn
*
* @param allowMonsterSpawn True to allow spawning of monsters, false to prevent.
*/
void setAllowMonsterSpawn(boolean allowMonsterSpawn);
/**
* Returns a list of monsters. This list always negates the {@link #canMonstersSpawn()} result.
*
* @return A list of monsters that will spawn if {@link #canMonstersSpawn()} is false.
*/
List<String> getMonsterList();
// end of animal&monster stuff
/**
* Gets whether or not PVP is enabled in this world in some form (fake or not).
*
* @return True if players can take damage from other players.
*/
boolean isPVPEnabled();
/**
* Turn pvp on or off. This setting is used to set the world's PVP mode.
*
* @param pvpMode True to enable PVP damage, false to disable it.
*/
void setPVPMode(boolean pvpMode);
/**
* Turn pvp on or off. This setting is used to set the world's PVP mode, and thus relies on fakePVP
*
* @return True if this world has fakepvp on
* @deprecated This is deprecated.
*/
@Deprecated
boolean getFakePVP();
/**
* Gets whether or not this world will display in chat, mvw and mvl regardless if a user has the
* access permissions to go to this world.
*
* @return True if the world will be hidden, false if not.
*/
boolean isHidden();
/**
* Sets whether or not this world will display in chat, mvw and mvl regardless if a user has the
* access permissions to go to this world.
*
* @param hidden Set
*/
void setHidden(boolean hidden);
/**
* Gets whether weather is enabled in this world.
*
* @return True if weather events will occur, false if not.
*/
boolean isWeatherEnabled();
/**
* Sets whether or not there will be weather events in a given world.
* If set to false, Multiverse will disable the weather in the world immediately.
*
* @param enableWeather True if weather events should occur in a world, false if not.
*/
void setEnableWeather(boolean enableWeather);
/**
* Gets whether or not CraftBukkit is keeping the chunks for this world in memory.
*
* @return True if CraftBukkit is keeping spawn chunks in memory.
*/
boolean isKeepingSpawnInMemory();
/**
* If true, tells Craftbukkit to keep a worlds spawn chunks loaded in memory (default: true)
* If not, CraftBukkit will attempt to free memory when players have not used that world.
* This will not happen immediately.
*
* @param keepSpawnInMemory If true, CraftBukkit will keep the spawn chunks loaded in memory.
*/
void setKeepSpawnInMemory(boolean keepSpawnInMemory);
/**
* Gets the spawn location of this world.
*
* @return The spawn location of this world.
*/
Location getSpawnLocation();
/**
* Sets the spawn location for a world.
*
* @param spawnLocation The spawn location for a world.
*/
void setSpawnLocation(Location spawnLocation);
/**
* Gets whether or not the hunger level of players will go down in a world.
*
* @return True if it will go down, false if it will remain steady.
*/
boolean getHunger();
/**
* Sets whether or not the hunger level of players will go down in a world.
*
* @param hungerEnabled True if hunger will go down, false to keep it at
* the level they entered a world with.
*/
void setHunger(boolean hungerEnabled);
/**
* Gets the GameMode of this world.
*
* @return The GameMode of this world.
*/
GameMode getGameMode();
/**
* Sets the game mode of this world.
*
* @param gameMode A valid game mode string (either
* an int ex. 0 or a string ex. creative).
* @return True if the game mode was successfully changed, false if not.
* @deprecated Use {@link #setGameMode(GameMode)} instead. If you have to
* pass a string, use {@link #setPropertyValue(String, String)}.
*/
@Deprecated
boolean setGameMode(String gameMode);
/**
* Sets the game mode of this world.
*
* @param gameMode The new {@link GameMode}.
* @return True if the game mode was successfully changed, false if not.
*/
boolean setGameMode(GameMode gameMode);
/**
* Gets the amount of currency it requires to enter this world.
*
* @return The amount it costs to enter this world.
*/
double getPrice();
/**
* Sets the price for entry to this world.
* You can think of this like an amount.
* The type can be set with {@link #setCurrency(Material)}
*
* @param price The Amount of money/item to enter the world.
*/
void setPrice(double price);
/**
* Gets the type of currency that will be used when users enter this world. A value of null indicates a non-item
* based currency is used.
*
* @return The type of currency that will be used when users enter this world.
*/
@Nullable
Material getCurrency();
/**
* Sets the type of item that will be required given the price is not 0.
* Use a value of null to specify a non-item based currency.
*
* @param item The Type of currency that will be used when users enter this world.
*/
void setCurrency(@Nullable Material item);
/**
* Gets the world players will respawn in if they die in this one.
*
* @return A world that exists on the server.
*/
World getRespawnToWorld();
/**
* Sets the world players will respawn in if they die in this one.
* Returns true upon success, false upon failure.
*
* @param respawnWorld The name of a world that exists on the server.
* @return True if respawnWorld existed, false if not.
*/
boolean setRespawnToWorld(String respawnWorld);
/**
* Gets the scaling value of this world.Really only has an effect if you use
* Multiverse-NetherPortals.
*
* @return This world's non-negative, non-zero scale.
*/
double getScaling();
/**
* Sets the scale of this world. Really only has an effect if you use
* Multiverse-NetherPortals.
*
* @param scaling A scaling value, cannot be negative or 0.
* @return Whether the scale was set successfully.
*/
boolean setScaling(double scaling);
/**
* Gets whether or not a world will auto-heal players if the difficulty is on peaceful.
*
* @return True if the world should heal (default), false if not.
*/
boolean getAutoHeal();
/**
* Sets whether or not a world will auto-heal players if the difficulty is on peaceful.
*
* @param heal True if the world will heal.
*/
void setAutoHeal(boolean heal);
/**
* Gets whether or not Multiverse should auto-adjust the spawn for this world.
*
* @return True if Multiverse should adjust the spawn, false if not.
*/
boolean getAdjustSpawn();
/**
* Sets whether or not Multiverse should auto-adjust the spawn for this world.
*
* @param adjust True if multiverse should adjust the spawn, false if not.
*/
void setAdjustSpawn(boolean adjust);
/**
* Gets whether or not Multiverse should auto-load this world.
*
* @return True if Multiverse should auto-load this world.
*/
boolean getAutoLoad();
/**
* Sets whether or not Multiverse should auto-load this world.
* <p>
* True is default.
*
* @param autoLoad True if multiverse should autoload this world the spawn, false if not.
*/
void setAutoLoad(boolean autoLoad);
/**
* Gets whether or not a player who dies in this world will respawn in their
* bed or follow the normal respawn pattern.
*
* @return True if players dying in this world should respawn at their bed.
*/
boolean getBedRespawn();
/**
* Sets whether or not a player who dies in this world will respawn in their
* bed or follow the normal respawn pattern.
* <p>
* True is default.
*
* @param autoLoad True if players dying in this world respawn at their bed.
*/
void setBedRespawn(boolean autoLoad);
/**
* Sets the player limit for this world after which players without an override
* permission node will not be allowed in. A value of -1 or less signifies no limit
*
* @param limit The new limit
*/
void setPlayerLimit(int limit);
/**
* Gets the player limit for this world after which players without an override
* permission node will not be allowed in. A value of -1 or less signifies no limit
*
* @return The player limit
*/
int getPlayerLimit();
/**
* Same as {@link #getTime()}, but returns a string.
* @return The time as a short string: 12:34pm
*/
String getTime();
/**
* Sets the current time in a world.
* <p>
* This method will take the following formats:
* 11:37am
* 4:30p
* day(morning), night, noon, midnight
*
* @param timeAsString The formatted time to set the world to.
* @return True if the time was set, false if not.
*/
boolean setTime(String timeAsString);
/**
* Sets The types of portals that are allowed in this world.
*
* @param type The type of portals allowed in this world.
*/
void allowPortalMaking(AllowedPortalType type);
/**
* Gets which type(s) of portals are allowed to be constructed in this world.
*
* @return The type of portals that are allowed.
*/
AllowedPortalType getAllowedPortals();
// properties that are not "getter+setter" style
/**
* Gets a list of all the worlds that players CANNOT travel to from this world,
* regardless of their access permissions.
*
* @return A List of world names.
*/
List<String> getWorldBlacklist();
/**
* Gets all the names of all properties that can be SET.
*
* @return All property names, with alternating colors.
*/
String getAllPropertyNames();
/**
* Whether or not players are allowed to fly in this world.
*
* @return True if players allowed to fly in this world.
*/
boolean getAllowFlight();
/**
* Sets whether or not players are allowed to fly in this world.
*
* @param allowFlight True to allow flight in this world.
*/
void setAllowFlight(final boolean allowFlight);
}
@@ -0,0 +1,325 @@
/******************************************************************************
* 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 com.onarandombox.MultiverseCore.api;
import java.util.Collection;
import java.util.List;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.WorldType;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.generator.ChunkGenerator;
import org.jvnet.hk2.annotations.Contract;
/**
* Multiverse 2 World Manager API
* <p>
* This API contains all of the world managing
* functions that your heart desires!
*/
@Contract
public interface MVWorldManager {
/**
* Add a new World to the Multiverse Setup.
*
* @param name World Name
* @param env Environment Type
* @param seedString The seed in the form of a string.
* If the seed is a Long,
* it will be interpreted as such.
* @param type The Type of the world to be made.
* @param generateStructures If true, this world will get NPC villages.
* @param generator The Custom generator plugin to use.
* @return True if the world is added, false if not.
*/
boolean addWorld(String name, Environment env, String seedString, WorldType type, Boolean generateStructures,
String generator);
/**
* Add a new World to the Multiverse Setup.
*
* @param name World Name
* @param env Environment Type
* @param seedString The seed in the form of a string.
* If the seed is a Long,
* it will be interpreted as such.
* @param type The Type of the world to be made.
* @param generateStructures If true, this world will get NPC villages.
* @param generator The Custom generator plugin to use.
* @param useSpawnAdjust If true, multiverse will search for a safe spawn. If not, It will not modify the level.dat.
* @return True if the world is added, false if not.
*/
boolean addWorld(String name, Environment env, String seedString, WorldType type, Boolean generateStructures,
String generator, boolean useSpawnAdjust);
/**
* Make a copy of a world.
*
* @param oldName
* Name of world to be copied
* @param newName
* Name of world to be created
* @return True if the world is copied successfully, false if not.
*/
boolean cloneWorld(String oldName, String newName);
/**
* Remove the world from the Multiverse list, from the config and deletes
* the folder.
*
* @param name
* The name of the world to remove
* @return True if success, false if failure.
*/
boolean deleteWorld(String name);
/**
* Remove the world from the Multiverse list, from the
* config if wanted, and deletes the folder.
*
* @param name The name of the world to remove
* @param removeConfig If true(default), we'll remove the entries from the
* config. If false, they'll stay and the world may come back.
* @return True if success, false if failure.
*/
boolean deleteWorld(String name, boolean removeConfig);
/**
*
* @param name The name of the world to remove
* @param removeFromConfig If true(default), we'll remove the entries from the
* config. If false, they'll stay and the world may come back.
* @param deleteWorldFolder If true the world folder will be completely deleted. If false
* only the contents of the world folder will be deleted
* @return True if success, false if failure.
*/
boolean deleteWorld(String name, boolean removeFromConfig, boolean deleteWorldFolder);
/**
* Unload a world from Multiverse.
*
* @param name Name of the world to unload
* @return True if the world was unloaded, false if not.
*/
boolean unloadWorld(String name);
/**
* Unload a world from Multiverse with option to prevent calling unloadWorld in Bukkit.
*
* @param name Name of the world to unload
* @param unloadBukkit True if Bukkit world should be unloaded
* @return True if the world was unloaded, false if not.
*/
boolean unloadWorld(String name, boolean unloadBukkit);
/**
* Loads the world. Only use this if the world has been
* unloaded with {@link #unloadWorld(String)}.
*
* @param name The name of the world to load
* @return True if success, false if failure.
*/
boolean loadWorld(String name);
/**
* Removes all players from the specified world.
*
* @param name World to remove players from.
*/
void removePlayersFromWorld(String name);
/**
* Test if a given chunk generator is valid.
*
* @param generator The generator name.
* @param generatorID The generator id.
* @param worldName The worldName to use as the default.
* @return A {@link ChunkGenerator} or null
*/
ChunkGenerator getChunkGenerator(String generator, String generatorID, String worldName);
/**
* Returns a list of all the worlds Multiverse knows about.
*
* @return A list of {@link MVWorld}.
*/
Collection<MVWorld> getMVWorlds();
/**
* Returns a {@link MVWorld} if it exists, and null if it does not.
* This will search name AND alias.
*
* @param name The name or alias of the world to get.
* @return A {@link MVWorld} or null.
*/
MVWorld getMVWorld(String name);
/**
* Returns a {@link MVWorld} if the world with name given exists, and null if it does not.
* This will search optionally for alias names.
*
* @param name The name or optionally the alias of the world to get.
* @param checkAliases Indicates whether to check for world alias name.
* @return A {@link MVWorld} or null.
*/
MVWorld getMVWorld(String name, boolean checkAliases);
/**
* Returns a {@link MVWorld} if it exists, and null if it does not.
*
* @param world The Bukkit world to check.
* @return A {@link MVWorld} or null.
*/
MVWorld getMVWorld(World world);
/**
* Checks to see if the given name is a valid {@link MVWorld}
* Searches based on world name AND alias.
*
* @param name The name or alias of the world to check.
* @return True if the world exists, false if not.
*/
boolean isMVWorld(String name);
/**
* Checks to see if the given name is a valid {@link MVWorld}.
* Optionally searches by alias is specified.
*
* @param name The name or alias of the world to check.
* @param checkAliases Indicates whether to check for world alias name.
* @return True if the world exists, false if not.
*/
boolean isMVWorld(String name, boolean checkAliases);
/**
* Checks to see if the given world is a valid {@link MVWorld}.
*
* @param world The Bukkit world to check.
* @return True if the world has been loaded into MV2, false if not.
*/
boolean isMVWorld(World world);
/**
* Load the Worlds &amp; Settings from the configuration file.
*
* @param forceLoad If set to true, this will perform a total
* reset and not just load new worlds.
*/
void loadWorlds(boolean forceLoad);
/**
* Loads the Worlds &amp; Settings for any worlds that bukkit loaded before us.
* <p>
* This way people will _always_ have some worlds in the list.
*/
void loadDefaultWorlds();
/**
* Gets the world players will spawn in on first join.
* Currently this always returns worlds.get(0) from Bukkit.
*
* @return A Multiverse world that players will spawn in or null if no MV world has been set.
*/
MVWorld getSpawnWorld();
/**
* Gets the list of worlds in the config, but unloaded.
*
* @return A List of worlds as strings.
*/
List<String> getUnloadedWorlds();
/**
* This method populates an internal list and needs to be called after multiverse initialization.
*/
void getDefaultWorldGenerators();
/**
* Load the config from a file.
*
* @return A loaded configuration.
*/
FileConfiguration loadWorldsConfig();
/**
* Saves the world config to disk.
*
* @return True if success, false if fail.
*/
boolean saveWorldsConfig();
/**
* Remove the world from the Multiverse list and from the config.
*
* @param name The name of the world to remove
* @return True if success, false if failure.
*/
boolean removeWorldFromConfig(String name);
/**
* Sets the initial spawn world for new players.
*
* @param world The World new players should spawn in.
*/
void setFirstSpawnWorld(String world);
/**
* Gets the world players should spawn in first.
*
* @return The {@link MVWorld} new players should spawn in.
*/
MVWorld getFirstSpawnWorld();
/**
* Regenerates a world.
*
* @param name Name of the world to regenerate
* @param useNewSeed If a new seed should be used
* @param randomSeed If the new seed should be random
* @param seed The seed of the world.
*
* @return True if success, false if fail.
*/
boolean regenWorld(String name, boolean useNewSeed, boolean randomSeed, String seed);
/**
* Regenerates a world.
*
* @param name Name of the world to regenerate
* @param useNewSeed If a new seed should be used
* @param randomSeed If the new seed should be random
* @param seed The seed of the world.
* @param keepGameRules If GameRules should be kept on world regen.
*
* @return True if success, false if fail.
*/
boolean regenWorld(String name, boolean useNewSeed, boolean randomSeed, String seed, boolean keepGameRules);
boolean isKeepingSpawnInMemory(World world);
/**
* Checks whether Multiverse knows about a provided unloaded world. This
* method will check the parameter against the alias mappings.
*
* @param name The name of the unloaded world
* @param includeLoaded The value to return if the world is loaded
*
* @return True if the world exists and is unloaded. False if the world
* does not exist. {@code includeLoaded} if the world exists and is loaded.
*/
boolean hasUnloadedWorld(String name, boolean includeLoaded);
/**
* Get all the possible worlds that Multiverse has detected to be importable.
*
* @return A collection of world names that are deemed importable.
*/
Collection<String> getPotentialWorlds();
}
@@ -0,0 +1,87 @@
package com.onarandombox.MultiverseCore.api;
import java.util.concurrent.CompletableFuture;
import co.aikar.commands.BukkitCommandIssuer;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.teleportation.TeleportResult;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.jvnet.hk2.annotations.Contract;
/**
* 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,33 @@
package com.onarandombox.MultiverseCore.api;
import java.util.concurrent.CompletableFuture;
import co.aikar.commands.BukkitCommandIssuer;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.teleportation.TeleportResult;
import org.bukkit.entity.Entity;
import org.jvnet.hk2.annotations.Contract;
@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,70 @@
package com.onarandombox.MultiverseCore.api;
import java.util.List;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.jvnet.hk2.annotations.Contract;
/**
* Used to remove animals from worlds that don't belong there.
*/
@Contract
public interface WorldPurger {
/**
* Synchronizes the given worlds with their settings.
*
* @param worlds A list of {@link MVWorld}
*/
void purgeWorlds(List<MVWorld> worlds);
/**
* Convenience method for {@link #purgeWorld(MVWorld, java.util.List, boolean, boolean)} that takes the settings from the world-config.
*
* @param world The {@link MVWorld}.
*/
void purgeWorld(MVWorld world);
/**
* Clear all animals/monsters that do not belong to a world according to the config.
*
* @param mvworld The {@link MVWorld}.
* @param thingsToKill A {@link List} of animals/monsters to be killed.
* @param negateAnimals Whether the monsters in the list should be negated.
* @param negateMonsters Whether the animals in the list should be negated.
*/
void purgeWorld(MVWorld mvworld, List<String> thingsToKill, boolean negateAnimals,
boolean negateMonsters);
/**
* Clear all animals/monsters that do not belong to a world according to the config.
*
* @param mvworld The {@link MVWorld}.
* @param thingsToKill A {@link List} of animals/monsters to be killed.
* @param negateAnimals Whether the monsters in the list should be negated.
* @param negateMonsters Whether the animals in the list should be negated.
* @param sender The {@link CommandSender} that initiated the action. He will/should be notified.
*/
void purgeWorld(MVWorld mvworld, List<String> thingsToKill, boolean negateAnimals,
boolean negateMonsters, CommandSender sender);
/**
* Determines whether the specified creature should be killed.
*
* @param e The creature.
* @param thingsToKill A {@link List} of animals/monsters to be killed.
* @param negateAnimals Whether the monsters in the list should be negated.
* @param negateMonsters Whether the animals in the list should be negated.
* @return {@code true} if the creature should be killed, otherwise {@code false}.
*/
boolean shouldWeKillThisCreature(Entity e, List<String> thingsToKill, boolean negateAnimals, boolean negateMonsters);
/**
* Determines whether the specified creature should be killed and automatically reads the params from a world object.
*
* @param w The world.
* @param e The creature.
* @return {@code true} if the creature should be killed, otherwise {@code false}.
*/
boolean shouldWeKillThisCreature(MVWorld w, Entity e);
}
@@ -2,4 +2,4 @@
* 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;
package com.onarandombox.MultiverseCore.api;
@@ -0,0 +1,53 @@
package com.onarandombox.MultiverseCore.commands;
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.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class CheckCommand extends MultiverseCommand {
private final DestinationsProvider destinationsProvider;
@Inject
public CheckCommand(@NotNull MVCommandManager commandManager, @NotNull DestinationsProvider destinationsProvider) {
super(commandManager);
this.destinationsProvider = destinationsProvider;
}
@Subcommand("check")
@CommandPermission("multiverse.core.check")
@CommandCompletion("@players @destinations|@mvworlds")
@Syntax("<player> <destination>")
@Description("{@@mv-core.check.description}")
public void onCheckCommand(BukkitCommandIssuer issuer,
@Syntax("<player>")
@Description("{@@mv-core.check.player.description}")
Player player,
@Syntax("<destination>")
@Description("{@@mv-core.check.destination.description}")
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);
}
}
@@ -0,0 +1,61 @@
package com.onarandombox.MultiverseCore.commands;
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.Conditions;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class CloneCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public CloneCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@Subcommand("clone")
@CommandPermission("multiverse.core.clone")
@CommandCompletion("@mvworlds:scope=both @empty")
@Syntax("<world> <new world name>")
@Description("{@@mv-core.clone.description}")
public void onCloneCommand(CommandIssuer issuer,
@Conditions("validWorldName:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.clone.world.description}")
String worldName,
@Single
@Conditions("validWorldName:scope=new")
@Syntax("<new world name>")
@Description("{@@mv-core.clone.newWorld.description}")
String newWorldName
) {
issuer.sendInfo(MVCorei18n.CLONE_CLONING,
"{world}", worldName,
"{newWorld}", newWorldName);
if (!this.worldManager.cloneWorld(worldName, newWorldName)) {
issuer.sendError(MVCorei18n.CLONE_FAILED);
return;
}
issuer.sendInfo(MVCorei18n.CLONE_SUCCESS,
"{world}", newWorldName);
}
}
@@ -1,66 +1,68 @@
package org.mvplugins.multiverse.core.commands;
package com.onarandombox.MultiverseCore.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.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.commandtools.MVCommandIssuer;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.context.MVConfigValue;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.exceptions.MultiverseException;
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.commandtools.MVCommandIssuer;
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.exceptions.MultiverseException;
@Service
@CommandAlias("mv")
class ConfigCommand extends MultiverseCommand {
public class ConfigCommand extends MultiverseCommand {
private final MVCoreConfig config;
@Inject
ConfigCommand(@NotNull MVCommandManager commandManager, @NotNull MVCoreConfig config) {
public 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("Show or set a config value.")
void onConfigCommand(
MVCommandIssuer issuer,
@CommandCompletion("@mvconfigs")
@Syntax("<name> [new-value]")
@Description("") //TODO
public void onConfigCommand(MVCommandIssuer issuer,
@Syntax("<name>")
@Description("The name of the config to set or show.")
String name,
@Syntax("<name>")
@Description("") //TODO
String name,
@Optional
@Syntax("[value]")
@Description("The value to set the config to. If not specified, the current value will be shown.")
String value) {
@Optional
@Single
@Syntax("[new-value]")
@Description("") //TODO
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)
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) {
config.getStringPropertyHandle().setPropertyString(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);
@@ -1,30 +1,29 @@
package org.mvplugins.multiverse.core.commands;
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
@Service
@CommandAlias("mv")
class ConfirmCommand extends MultiverseCommand {
public class ConfirmCommand extends MultiverseCommand {
@Inject
ConfirmCommand(@NotNull MVCommandManager commandManager) {
public ConfirmCommand(@NotNull MVCommandManager commandManager) {
super(commandManager);
}
@Subcommand("confirm")
@CommandPermission("multiverse.core.confirm")
@Description("{@@mv-core.confirm.description}")
void onConfirmCommand(@NotNull BukkitCommandIssuer issuer) {
public void onConfirmCommand(@NotNull BukkitCommandIssuer issuer) {
this.commandManager.getCommandQueueManager().runQueuedCommand(issuer.getIssuer());
}
}
@@ -0,0 +1,143 @@
package com.onarandombox.MultiverseCore.commands;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.InvalidCommandArgument;
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.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper;
import jakarta.inject.Inject;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldType;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class CreateCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public CreateCommand(
@NotNull MVCommandManager commandManager,
@NotNull MVWorldManager worldManager,
@NotNull UnsafeCallWrapper unsafeCallWrapper
) {
super(commandManager);
this.worldManager = worldManager;
registerFlagGroup(CommandFlagGroup.builder("mvcreate")
.add(CommandValueFlag.builder("--seed", String.class)
.addAlias("-s")
.completion(() -> Collections.singleton(String.valueOf(new Random().nextLong())))
.build())
.add(CommandValueFlag.builder("--generator", String.class)
.addAlias("-g")
.completion(() -> Arrays.stream(Bukkit.getServer().getPluginManager().getPlugins())
.filter(Plugin::isEnabled)
.filter(genplugin -> unsafeCallWrapper.wrap(
() -> genplugin.getDefaultWorldGenerator("world", ""),
genplugin.getName(),
"Get generator"
) != null)
.map(genplugin -> genplugin.getDescription().getName())
.collect(Collectors.toList()))
.build())
.add(CommandValueFlag.builder("--world-type", WorldType.class)
.addAlias("-t")
.context((value) -> {
try {
return WorldType.valueOf(value.toUpperCase());
} catch (IllegalArgumentException e) {
throw new InvalidCommandArgument("Invalid world type: " + value);
}
})
.completion(() -> {
List<String> types = new ArrayList<>();
for (WorldType type : WorldType.values()) {
types.add(type.name().toLowerCase());
}
return types;
})
.build())
.add(CommandFlag.builder("--adjust-spawn")
.addAlias("-n")
.build())
.add(CommandFlag.builder("--no-structures")
.addAlias("-a")
.build())
.build());
}
@Subcommand("create")
@CommandPermission("multiverse.core.create")
@CommandCompletion("@empty @flags:groupName=mvcreate")
@Syntax("<name> <environment> --seed [seed] --generator [generator[:id]] --world-type [worldtype] --adjust-spawn --no-structures")
@Description("{@@mv-core.create.description}")
public void onCreateCommand(BukkitCommandIssuer issuer,
@Conditions("validWorldName:scope=new")
@Syntax("<name>")
@Description("{@@mv-core.create.name.description}")
String worldName,
@Syntax("<environment>")
@Description("{@@mv-core.create.environment.description}")
World.Environment environment,
@Optional
@Syntax("--seed [seed] --generator [generator[:id]] --world-type [worldtype] --adjust-spawn --no-structures")
@Description("{@@mv-core.create.flags.description}")
String[] flags
) {
ParsedCommandFlags parsedFlags = parseFlags(flags);
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", "RANDOM", String.class));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_WORLDTYPE, "{worldType}", parsedFlags.flagValue("--world-type", WorldType.NORMAL, WorldType.class).name());
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_ADJUSTSPAWN, "{adjustSpawn}", String.valueOf(parsedFlags.hasFlag("--adjust-spawn")));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_GENERATOR, "{generator}", parsedFlags.flagValue("--generator", "null", String.class));
issuer.sendInfo(MVCorei18n.CREATE_PROPERTIES_STRUCTURES, "{structures}", String.valueOf(!parsedFlags.hasFlag("--no-structures")));
issuer.sendInfo(MVCorei18n.CREATE_LOADING);
if (!worldManager.addWorld(
worldName,
environment,
parsedFlags.flagValue("--seed", String.class),
parsedFlags.flagValue("--world-type", WorldType.NORMAL, WorldType.class),
parsedFlags.hasFlag("--adjust-spawn"),
parsedFlags.flagValue("--generator", String.class),
parsedFlags.hasFlag("--no-structures")
)) {
issuer.sendError(MVCorei18n.CREATE_FAILED, "{worldName}", worldName);
return;
}
issuer.sendInfo(MVCorei18n.CREATE_SUCCESS, "{worldName}", worldName);
}
}
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.commands;
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
@@ -8,23 +8,22 @@ import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
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
@CommandAlias("mv")
class DebugCommand extends MultiverseCommand {
public class DebugCommand extends MultiverseCommand {
private final MVCoreConfig config;
@Inject
DebugCommand(@NotNull MVCommandManager commandManager, @NotNull MVCoreConfig config) {
public DebugCommand(@NotNull MVCommandManager commandManager, @NotNull MVCoreConfig config) {
super(commandManager);
this.config = config;
}
@@ -32,7 +31,7 @@ class DebugCommand extends MultiverseCommand {
@Subcommand("debug")
@CommandPermission("multiverse.core.debug")
@Description("{@@mv-core.debug.info.description}")
void onShowDebugCommand(BukkitCommandIssuer issuer) {
public void onShowDebugCommand(BukkitCommandIssuer issuer) {
this.displayDebugMode(issuer);
}
@@ -41,12 +40,11 @@ class DebugCommand extends MultiverseCommand {
@CommandCompletion("@range:3")
@Syntax("<{@@mv-core.debug.change.syntax}>")
@Description("{@@mv-core.debug.change.description}")
void onChangeDebugCommand(
BukkitCommandIssuer issuer,
public void onChangeDebugCommand(BukkitCommandIssuer issuer,
@Syntax("<{@@mv-core.debug.change.syntax}>")
@Description("{@@mv-core.debug.change.level.description}")
int level) {
@Syntax("<{@@mv-core.debug.change.syntax}>")
@Description("{@@mv-core.debug.change.level.description}")
int level) {
config.setGlobalDebug(level);
config.save();
@@ -0,0 +1,67 @@
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.BukkitCommandIssuer;
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.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class DeleteCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public DeleteCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@Subcommand("delete")
@CommandPermission("multiverse.core.delete")
@CommandCompletion("@mvworlds:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.delete.description}")
public void onDeleteCommand(BukkitCommandIssuer issuer,
@Single
@Conditions("validWorldName:scope=both")
@Syntax("<world>")
@Description("The world you want to delete.")
String worldName
) {
this.commandManager.getCommandQueueManager().addToQueue(new QueuedCommand(
issuer.getIssuer(),
() -> {
issuer.sendInfo(MVCorei18n.DELETE_DELETING,
"{world}", worldName);
if (!this.worldManager.deleteWorld(worldName)) {
issuer.sendError(MVCorei18n.DELETE_FAILED,
"{world}", worldName);
return;
}
issuer.sendInfo(MVCorei18n.DELETE_SUCCESS,
"{world}", worldName);
},
this.commandManager.formatMessage(
issuer,
MessageType.INFO,
MVCorei18n.DELETE_PROMPT,
"{world}", worldName)
));
}
}
@@ -0,0 +1,79 @@
package com.onarandombox.MultiverseCore.commands;
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.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.context.GameRuleValue;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.bukkit.GameRule;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class GameruleCommand extends MultiverseCommand {
@Inject
public GameruleCommand(@NotNull MVCommandManager commandManager) {
super(commandManager);
}
@Subcommand("gamerule")
@CommandPermission("multiverse.core.gamerule")
@CommandCompletion("@gamerules true|false|@range:1-10 @mvworlds:multiple|*")
@Syntax("<Gamerule> <Gamerule value> [World or *]")
@Description("{@@mv-core.gamerule.description}")
public void onGameruleCommand(BukkitCommandIssuer issuer,
@Syntax("<Gamerule>")
@Description("{@@mv-core.gamerule.gamerule.description}")
GameRule gamerule,
@Syntax("<Value>")
@Description("{@@mv-core.gamerule.value.description}")
GameRuleValue gameRuleValue,
@Flags("resolve=issuerAware")
@Syntax("[World or *]")
@Description("{@@mv-core.gamerule.world.description}")
MVWorld[] worlds
) {
Object value = gameRuleValue.getValue();
boolean success = true;
for(MVWorld world : worlds) {
// Set gamerules and add false to list if it fails
if (!world.getCBWorld().setGameRule(gamerule, value)) {
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_SUCCESS_SINGLE,
"{gamerule}", gamerule.getName(),
"{value}", value.toString(),
"{world}", worlds[0].getName());
}
else if (worlds.length > 1) {
issuer.sendInfo(MVCorei18n.GAMERULE_SUCCESS_MULTIPLE,
"{gamerule}", gamerule.getName(),
"{value}", value.toString(),
"{count}", String.valueOf(worlds.length));
}
}
}
}
@@ -0,0 +1,104 @@
package com.onarandombox.MultiverseCore.commands;
import java.util.Arrays;
import java.util.stream.Collectors;
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.Conditions;
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.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper;
import jakarta.inject.Inject;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class ImportCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public ImportCommand(
@NotNull MVCommandManager commandManager,
@NotNull MVWorldManager worldManager,
@NotNull UnsafeCallWrapper unsafeCallWrapper
) {
super(commandManager);
this.worldManager = worldManager;
registerFlagGroup(CommandFlagGroup.builder("mvimport")
.add(CommandValueFlag.builder("--generator", String.class)
.addAlias("-g")
.completion(() -> Arrays.stream(Bukkit.getServer().getPluginManager().getPlugins())
.filter(Plugin::isEnabled)
.filter(genplugin -> unsafeCallWrapper.wrap(
() -> genplugin.getDefaultWorldGenerator("world", ""),
genplugin.getName(),
"Get generator"
) != null)
.map(genplugin -> genplugin.getDescription().getName())
.collect(Collectors.toList()))
.build())
.add(CommandFlag.builder("--adjust-spawn")
.addAlias("-a")
.build())
.build());
}
@Subcommand("import")
@CommandPermission("multiverse.core.import")
@CommandCompletion("@mvworlds:scope=potential @flags:groupName=mvimport")
@Syntax("<name> <env> --generator [generator[:id]] --adjust-spawn")
@Description("{@@mv-core.import.description")
public void onImportCommand(BukkitCommandIssuer issuer,
@Conditions("validWorldName:scope=new")
@Syntax("<name>")
@Description("{@@mv-core.import.name.description}")
String worldName,
@Syntax("<env>")
@Description("{@@mv-core.import.env.description}")
World.Environment environment,
@Optional
@Syntax("--generator [generator[:id]] --adjust-spawn")
@Description("{@@mv-core.import.other.description}")
String[] flags) {
ParsedCommandFlags parsedFlags = parseFlags(flags);
issuer.sendInfo(MVCorei18n.IMPORT_IMPORTING,
"{world}", worldName);
if (!this.worldManager.addWorld(
worldName, environment,
null,
null,
null,
parsedFlags.flagValue("--generator", String.class),
parsedFlags.hasFlag("--adjust-spawn"))
) {
issuer.sendError(MVCorei18n.IMPORT_FAILED);
return;
}
issuer.sendInfo(MVCorei18n.IMPORT_SUCCESS);
}
}
@@ -0,0 +1,56 @@
package com.onarandombox.MultiverseCore.commands;
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.Conditions;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class LoadCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public LoadCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@Subcommand("load")
@CommandPermission("multiverse.core.load")
@CommandCompletion("@mvworlds:scope=unloaded")
@Syntax("<world>")
@Description("{@@mv-core.load.description}")
public void onLoadCommand(BukkitCommandIssuer issuer,
@Single
@Conditions("validWorldName:scope=unloaded")
@Syntax("<world>")
@Description("{@@mv-core.load.world.description}")
String worldName
) {
issuer.sendInfo(MVCorei18n.LOAD_LOADING,
"{world}", worldName);
if (!this.worldManager.loadWorld(worldName)) {
issuer.sendError(MVCorei18n.LOAD_FAILED,
"{world}", worldName);
return;
}
issuer.sendInfo(MVCorei18n.LOAD_SUCCESS,
"{world}", worldName);
}
}
@@ -0,0 +1,97 @@
package com.onarandombox.MultiverseCore.commands;
import java.util.Collections;
import java.util.Random;
import co.aikar.commands.BukkitCommandIssuer;
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.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class RegenCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public RegenCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
registerFlagGroup(CommandFlagGroup.builder("mvregen")
.add(CommandValueFlag.builder("--seed", String.class)
.addAlias("-s")
.completion(() -> Collections.singleton(String.valueOf(new Random().nextLong())))
.optional()
.build())
.add(CommandFlag.builder("--keep-gamerules")
.addAlias("-k")
.build())
.build());
}
@Subcommand("regen")
@CommandPermission("multiverse.core.regen")
@CommandCompletion("@mvworlds:scope=both @flags:groupName=mvregen")
@Syntax("<world> --seed [seed] --keep-gamerules")
@Description("{@@mv-core.regen.description}")
public void onRegenCommand(BukkitCommandIssuer issuer,
@Conditions("validWorldName:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.regen.world.description}")
String worldName,
@Optional
@Syntax("--seed [seed] --keep-gamerules")
@Description("{@@mv-core.regen.other.description}")
String[] flags
) {
ParsedCommandFlags parsedFlags = parseFlags(flags);
this.commandManager.getCommandQueueManager().addToQueue(new QueuedCommand(
issuer.getIssuer(),
() -> {
issuer.sendInfo(MVCorei18n.REGEN_REGENERATING,
"{world}", worldName);
if (!this.worldManager.regenWorld(
worldName,
parsedFlags.hasFlag("--seed"),
!parsedFlags.hasFlagValue("--seed"),
parsedFlags.flagValue("--seed", String.class),
parsedFlags.hasFlag("--keep-gamerules")
)) {
issuer.sendError(MVCorei18n.REGEN_FAILED,
"{world}", worldName);
return;
}
issuer.sendInfo(MVCorei18n.REGEN_SUCCESS,
"{world}", worldName);
},
this.commandManager.formatMessage(
issuer,
MessageType.INFO,
MVCorei18n.REGEN_PROMPT,
"{world}", worldName)
));
}
}
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.commands;
package com.onarandombox.MultiverseCore.commands;
import java.util.ArrayList;
import java.util.List;
@@ -8,35 +8,37 @@ import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.anchor.AnchorManager;
import com.onarandombox.MultiverseCore.api.MVCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.event.MVConfigReloadEvent;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.bukkit.plugin.PluginManager;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.anchor.AnchorManager;
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.utils.MVCorei18n;
import org.mvplugins.multiverse.core.world.WorldManager;
@Service
@CommandAlias("mv")
class ReloadCommand extends MultiverseCommand {
public class ReloadCommand extends MultiverseCommand {
private final MVCoreConfig config;
private final AnchorManager anchorManager;
private final WorldManager worldManager;
private final MVWorldManager worldManager;
private final PluginManager pluginManager;
@Inject
ReloadCommand(
public ReloadCommand(
@NotNull MVCommandManager commandManager,
@NotNull MVCoreConfig config,
@NotNull AnchorManager anchorManager,
@NotNull WorldManager worldManager,
@NotNull PluginManager pluginManager) {
@NotNull MVWorldManager worldManager,
@NotNull PluginManager pluginManager
) {
super(commandManager);
this.config = config;
this.anchorManager = anchorManager;
@@ -47,26 +49,22 @@ class ReloadCommand extends MultiverseCommand {
@Subcommand("reload")
@CommandPermission("multiverse.core.reload")
@Description("{@@mv-core.reload.description}")
void onReloadCommand(@NotNull BukkitCommandIssuer issuer) {
public 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();
} catch (Exception e) {
e.printStackTrace();
}
this.config.load();
this.worldManager.loadWorldsConfig();
this.worldManager.loadWorlds(true);
this.anchorManager.loadAnchors();
List<String> configsLoaded = new ArrayList<>();
configsLoaded.add("Multiverse-Core - config.yml");
configsLoaded.add("Multiverse-Core - worlds2.yml");
configsLoaded.add("Multiverse-Core - worlds.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?
// @TODO: replace this sendMessage and format the configsLoaded above, maybe?
configReload.getAllConfigsLoaded().forEach(issuer::sendMessage);
issuer.sendInfo(MVCorei18n.RELOAD_SUCCESS);
}
@@ -0,0 +1,52 @@
package com.onarandombox.MultiverseCore.commands;
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.Conditions;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class RemoveCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public RemoveCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@Subcommand("remove")
@CommandPermission("multiverse.core.remove")
@CommandCompletion("@mvworlds:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.remove.description}")
public void onRemoveCommand(BukkitCommandIssuer issuer,
@Single
@Conditions("mvworlds:scope=both")
@Syntax("<world>")
@Description("{@@mv-core.remove.world.description}")
String worldName
) {
if (!this.worldManager.removeWorldFromConfig(worldName)) {
issuer.sendError(MVCorei18n.REMOVE_FAILED);
return;
}
issuer.sendInfo(MVCorei18n.REMOVE_SUCCESS,
"{world}", worldName);
}
}
@@ -1,31 +1,30 @@
package org.mvplugins.multiverse.core.commands;
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.CommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
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.utils.MVCorei18n;
@Service
class RootCommand extends MultiverseCommand {
public class RootCommand extends MultiverseCommand {
private final Plugin plugin;
@Inject
RootCommand(@NotNull MVCommandManager commandManager, @NotNull MultiverseCore plugin) {
public RootCommand(@NotNull MVCommandManager commandManager, @NotNull MultiverseCore plugin) {
super(commandManager);
this.plugin = plugin;
}
@CommandAlias("mv")
void onRootCommand(CommandIssuer issuer) {
public void onRootCommand(CommandIssuer issuer) {
PluginDescriptionFile description = this.plugin.getDescription();
issuer.sendInfo(MVCorei18n.ROOT_TITLE,
"{name}", description.getName(),
@@ -0,0 +1,69 @@
package com.onarandombox.MultiverseCore.commands;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.CommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Flags;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.bukkit.entity.Player;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class TeleportCommand extends MultiverseCommand {
private final DestinationsProvider destinationsProvider;
@Inject
public TeleportCommand(MVCommandManager commandManager, DestinationsProvider destinationsProvider) {
super(commandManager);
this.destinationsProvider = destinationsProvider;
}
@Subcommand("teleport|tp")
@CommandCompletion("@players|@mvworlds:playerOnly|@destinations:playerOnly @mvworlds|@destinations")
@Syntax("[player] <destination>")
@Description("{@@mv-core.teleport.description}")
public void onTeleportCommand(BukkitCommandIssuer issuer,
@Flags("resolve=issuerAware")
@Syntax("[player]")
@Description("{@@mv-core.teleport.player.description}")
Player[] players,
@Syntax("<destination>")
@Description("{@@mv-core.teleport.destination.description}")
ParsedDestination<?> destination
) {
// TODO Add warning if teleporting too many players at once.
CompletableFuture.allOf(Arrays.stream(players)
.map(player -> this.destinationsProvider.playerTeleportAsync(issuer, player, destination))
.toArray(CompletableFuture[]::new))
.thenRun(() -> {
String playerName = players.length == 1
? issuer.getPlayer() == players[0] ? "you" : players[0].getName()
: players.length + " players";
issuer.sendInfo(MVCorei18n.TELEPORT_SUCCESS,
"{player}", playerName, "{destination}", destination.toString());
});
}
@Override
public boolean hasPermission(CommandIssuer issuer) {
return this.destinationsProvider.hasAnyTeleportPermission(issuer);
}
}
@@ -0,0 +1,54 @@
package com.onarandombox.MultiverseCore.commands;
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.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
@CommandAlias("mv")
public class UnloadCommand extends MultiverseCommand {
private final MVWorldManager worldManager;
@Inject
public UnloadCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
super(commandManager);
this.worldManager = worldManager;
}
@Subcommand("unload")
@CommandPermission("multiverse.core.unload")
@CommandCompletion("@mvworlds")
@Syntax("<world>")
@Description("{@@mv-core.unload.description}")
public void onUnloadCommand(BukkitCommandIssuer issuer,
@Syntax("<world>")
@Description("{@@mv-core.unload.world.description}")
MVWorld world
) {
issuer.sendInfo(MVCorei18n.UNLOAD_UNLOADING,
"{world}", world.getColoredWorldString());
//TODO API: Should be able to use MVWorld object directly
if (!this.worldManager.unloadWorld(world.getName())) {
issuer.sendError(MVCorei18n.UNLOAD_FAILURE,
"{world}", world.getColoredWorldString());
return;
}
issuer.sendInfo(MVCorei18n.UNLOAD_SUCCESS,
"{world}", world.getColoredWorldString());
}
}
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.commands;
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.CommandHelp;
import co.aikar.commands.annotation.CommandAlias;
@@ -8,19 +8,18 @@ import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.HelpCommand;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
import jakarta.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
@Service
@CommandAlias("mv")
class UsageCommand extends MultiverseCommand {
public class UsageCommand extends MultiverseCommand {
@Inject
UsageCommand(@NotNull MVCommandManager commandManager) {
public UsageCommand(@NotNull MVCommandManager commandManager) {
super(commandManager);
}
@@ -30,7 +29,7 @@ class UsageCommand extends MultiverseCommand {
@CommandCompletion("@commands:mv")
@Syntax("[filter] [page]")
@Description("{@@mv-core.usage.description}")
void onUsageCommand(CommandHelp help) {
public void onUsageCommand(CommandHelp help) {
if (help.getIssuer().isPlayer()) {
// Prevent flooding the chat
help.setPerPage(4);
@@ -1,4 +1,4 @@
/**
* This package contains all the commands for Multiverse-Core.
*/
package org.mvplugins.multiverse.core.commands;
package com.onarandombox.MultiverseCore.commands;
@@ -0,0 +1,146 @@
package com.onarandombox.MultiverseCore.commandtools;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandCompletionContext;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.CommandIssuer;
import co.aikar.commands.PaperCommandCompletions;
import co.aikar.commands.RegisteredCommand;
import co.aikar.commands.RootCommand;
import com.google.common.collect.Sets;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import jakarta.inject.Inject;
import org.bukkit.GameRule;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
@Service
public class MVCommandCompletions extends PaperCommandCompletions {
protected final MVCommandManager commandManager;
private final MVWorldManager worldManager;
private final DestinationsProvider destinationsProvider;
@Inject
public MVCommandCompletions(
@NotNull MVCommandManager mvCommandManager,
@NotNull MVWorldManager worldManager,
@NotNull DestinationsProvider destinationsProvider,
@NotNull MVCoreConfig config
) {
super(mvCommandManager);
this.commandManager = mvCommandManager;
this.worldManager = worldManager;
this.destinationsProvider = destinationsProvider;
registerAsyncCompletion("commands", this::suggestCommands);
registerAsyncCompletion("destinations", this::suggestDestinations);
registerAsyncCompletion("flags", this::suggestFlags);
registerStaticCompletion("gamerules", this::suggestGamerules);
registerStaticCompletion("mvconfigs", config.getNodes().getNames());
registerAsyncCompletion("mvworlds", this::suggestMVWorlds);
setDefaultCompletion("destinations", ParsedDestination.class);
setDefaultCompletion("flags", String[].class);
setDefaultCompletion("gamerules", GameRule.class);
setDefaultCompletion("mvworlds", MVWorld.class);
}
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) {
if (context.hasConfig("playerOnly") && !context.getIssuer().isPlayer()) {
return Collections.emptyList();
}
return this.destinationsProvider
.suggestDestinations((BukkitCommandIssuer)context.getIssuer(), context.getInput());
}
private Collection<String> suggestFlags(@NotNull BukkitCommandCompletionContext context) {
return this.commandManager.getFlagsManager().suggest(
context.getConfig("groupName", ""), context.getContextValue(String[].class));
}
private Collection<String> suggestGamerules() {
return Arrays.stream(GameRule.values()).map(GameRule::getName).collect(Collectors.toList());
}
private Collection<String> suggestMVWorlds(BukkitCommandCompletionContext context) {
if (context.hasConfig("playerOnly") && !context.getIssuer().isPlayer()) {
return Collections.emptyList();
}
if (!context.hasConfig("multiple")) {
return getMVWorldNames(context);
}
String input = context.getInput();
int lastComma = input.lastIndexOf(',');
String currentWorldsString = input.substring(0, lastComma + 1);
Set<String> currentWorlds = Sets.newHashSet(input.split(","));
return getMVWorldNames(context).stream()
.filter(world -> !currentWorlds.contains(world))
.map(world -> currentWorldsString + world)
.collect(Collectors.toList());
}
private List<String> getMVWorldNames(BukkitCommandCompletionContext context) {
String scope = context.getConfig("scope", "loaded");
List<String> worlds = new ArrayList<>();
switch (scope) {
case "both":
worlds.addAll(worldManager.getUnloadedWorlds());
case "loaded":
worldManager.getMVWorlds()
.stream()
.map(MVWorld::getName)
.forEach(worlds::add);
break;
case "unloaded":
worlds.addAll(worldManager.getUnloadedWorlds());
break;
case "potential":
worlds.addAll(worldManager.getPotentialWorlds());
break;
}
return worlds;
}
}
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.commandtools;
package com.onarandombox.MultiverseCore.commandtools;
import co.aikar.commands.BukkitCommandExecutionContext;
import co.aikar.commands.BukkitCommandIssuer;
@@ -6,54 +6,49 @@ import co.aikar.commands.BukkitConditionContext;
import co.aikar.commands.CommandConditions;
import co.aikar.commands.ConditionContext;
import co.aikar.commands.ConditionFailedException;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.world.WorldNameChecker;
import jakarta.annotation.PostConstruct;
import org.jetbrains.annotations.NotNull;
import org.mvplugins.multiverse.core.world.WorldNameChecker;
import org.mvplugins.multiverse.core.world.WorldManager;
public class MVCommandConditions {
static void load(MVCommandManager commandManager, WorldManager worldManager, WorldNameChecker worldNameChecker) {
new MVCommandConditions(commandManager, worldManager, worldNameChecker);
static void load(MVCommandManager commandManager, MVWorldManager worldManager) {
new MVCommandConditions(commandManager, worldManager);
}
private final WorldManager worldManager;
private final MVWorldManager worldManager;
private final MVCommandManager commandManager;
private final WorldNameChecker worldNameChecker;
private MVCommandConditions(
@NotNull MVCommandManager commandManager,
@NotNull WorldManager worldManager,
@NotNull WorldNameChecker worldNameChecker) {
private MVCommandConditions(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
this.worldManager = worldManager;
this.commandManager = commandManager;
this.worldNameChecker = worldNameChecker;
registerConditions();
}
@PostConstruct
private void registerConditions() {
CommandConditions<BukkitCommandIssuer, BukkitCommandExecutionContext, BukkitConditionContext> conditions
= commandManager.getCommandConditions();
conditions.addCondition(String.class, "worldname", this::checkWorldname);
conditions.addCondition(String.class, "validWorldName", this::checkValidWorldName);
}
private void checkWorldname(
ConditionContext<BukkitCommandIssuer> context,
BukkitCommandExecutionContext executionContext,
String worldName) {
private void checkValidWorldName(ConditionContext<BukkitCommandIssuer> context,
BukkitCommandExecutionContext executionContext,
String worldName
) {
String scope = context.getConfigValue("scope", "loaded");
switch (scope) {
// Worlds that are loaded
case "loaded":
if (!this.worldManager.isLoadedWorld(worldName)) {
if (!this.worldManager.isMVWorld(worldName)) {
throw new ConditionFailedException("World with name '" + worldName + "' does not exist or is not loaded!");
}
break;
// Worlds that are unloaded
case "unloaded":
if (!this.worldManager.isUnloadedWorld(worldName)) {
if (this.worldManager.isLoadedWorld(worldName)) {
if (!this.worldManager.hasUnloadedWorld(worldName, false)) {
if (this.worldManager.isMVWorld(worldName)) {
throw new ConditionFailedException("World with name '" + worldName + "' is loaded already!");
}
throw new ConditionFailedException("World with name '" + worldName + "' does not exist!");
@@ -61,20 +56,20 @@ public class MVCommandConditions {
break;
// World that are loaded or unloaded
case "both":
if (!this.worldManager.isWorld(worldName)) {
if (!this.worldManager.hasUnloadedWorld(worldName, true)) {
throw new ConditionFailedException("World with name '" + worldName + "' does not exist!");
}
break;
// World that are does not exist
case "new":
if (this.worldManager.isWorld(worldName)) {
if (this.worldManager.hasUnloadedWorld(worldName, true)) {
throw new ConditionFailedException("World with name '" + worldName + "' already exists!");
}
switch (worldNameChecker.checkName(worldName)) {
case INVALID_CHARS ->
throw new ConditionFailedException("World name '" + worldName + "' contains invalid characters!");
case BLACKLISTED ->
throw new ConditionFailedException("World name '" + worldName + "' is used for critical server operations and is blacklisted!");
switch (WorldNameChecker.checkName(worldName)) {
case INVALID_CHARS:
throw new ConditionFailedException("World name '" + worldName + "' contains invalid characters!");
case BLACKLISTED:
throw new ConditionFailedException("World name '" + worldName + "' is used for critical server operations and is blacklisted!");
}
break;
// Probably a typo happened here
@@ -1,6 +1,7 @@
package org.mvplugins.multiverse.core.commandtools;
package com.onarandombox.MultiverseCore.commandtools;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import co.aikar.commands.BukkitCommandExecutionContext;
@@ -9,37 +10,40 @@ import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.PaperCommandContexts;
import co.aikar.commands.contexts.ContextResolver;
import com.google.common.base.Strings;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.context.GameRuleValue;
import com.onarandombox.MultiverseCore.commandtools.context.MVConfigValue;
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
import com.onarandombox.MultiverseCore.configuration.node.Node;
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.display.filters.ContentFilter;
import com.onarandombox.MultiverseCore.display.filters.DefaultContentFilter;
import com.onarandombox.MultiverseCore.display.filters.RegexContentFilter;
import com.onarandombox.MultiverseCore.utils.PlayerFinder;
import io.vavr.control.Option;
import jakarta.inject.Inject;
import org.bukkit.GameRule;
import org.bukkit.entity.Player;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.context.GameRuleValue;
import org.mvplugins.multiverse.core.config.MVCoreConfig;
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
import org.mvplugins.multiverse.core.destination.ParsedDestination;
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.utils.PlayerFinder;
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
import org.mvplugins.multiverse.core.world.MultiverseWorld;
import org.mvplugins.multiverse.core.world.WorldManager;
@Service
class MVCommandContexts extends PaperCommandContexts {
public class MVCommandContexts extends PaperCommandContexts {
private final MVCommandManager mvCommandManager;
private final DestinationsProvider destinationsProvider;
private final WorldManager worldManager;
private final MVWorldManager worldManager;
private final MVCoreConfig config;
@Inject
MVCommandContexts(
public MVCommandContexts(
MVCommandManager mvCommandManager,
DestinationsProvider destinationsProvider,
WorldManager worldManager,
MVCoreConfig config) {
MVWorldManager worldManager,
MVCoreConfig config
) {
super(mvCommandManager);
this.mvCommandManager = mvCommandManager;
this.destinationsProvider = destinationsProvider;
@@ -52,9 +56,9 @@ class MVCommandContexts extends PaperCommandContexts {
registerContext(ParsedDestination.class, this::parseDestination);
registerContext(GameRule.class, this::parseGameRule);
registerContext(GameRuleValue.class, this::parseGameRuleValue);
registerIssuerAwareContext(LoadedMultiverseWorld.class, this::parseLoadedMultiverseWorld);
registerIssuerAwareContext(LoadedMultiverseWorld[].class, this::parseLoadedMultiverseWorldArray);
registerIssuerAwareContext(MultiverseWorld.class, this::parseMultiverseWorld);
registerContext(MVConfigValue.class, this::parseMVConfigValue);
registerIssuerAwareContext(MVWorld.class, this::parseMVWorld);
registerIssuerAwareContext(MVWorld[].class, this::parseMVWorldArray);
registerIssuerAwareContext(Player.class, this::parsePlayer);
registerIssuerAwareContext(Player[].class, this::parsePlayerArray);
}
@@ -125,13 +129,46 @@ class MVCommandContexts extends PaperCommandContexts {
return new GameRuleValue(resolvedValue);
}
private LoadedMultiverseWorld parseLoadedMultiverseWorld(BukkitCommandExecutionContext context) {
private MVConfigValue parseMVConfigValue(BukkitCommandExecutionContext context) {
String configName = (String) context.getResolvedArg(String.class);
if (Strings.isNullOrEmpty(configName)) {
throw new InvalidCommandArgument("No config name specified.");
}
Option<Node> node = config.getNodes().findNode(configName);
if (node.isEmpty()) {
throw new InvalidCommandArgument("The config " + configName + " is not valid.");
}
String valueString = context.getFirstArg();
if (Strings.isNullOrEmpty(valueString)) {
throw new InvalidCommandArgument("No config value specified.");
}
if (!(node.get() instanceof ValueNode)) {
context.popFirstArg();
return new MVConfigValue(valueString);
}
ContextResolver<?, BukkitCommandExecutionContext> resolver = getResolver(((ValueNode<?>) node.get()).getType());
if (resolver == null) {
context.popFirstArg();
return new MVConfigValue(valueString);
}
Object resolvedValue = resolver.getContext(context);
if (resolvedValue == null) {
throw new InvalidCommandArgument("The config value " + valueString + " is not valid for config " + configName + ".");
}
return new MVConfigValue(resolvedValue);
}
private MVWorld parseMVWorld(BukkitCommandExecutionContext context) {
String resolve = context.getFlagValue("resolve", "");
// Get world based on sender only
if (resolve.equals("issuerOnly")) {
if (context.getIssuer().isPlayer()) {
return worldManager.getLoadedWorld(context.getIssuer().getPlayer().getWorld()).getOrNull();
return worldManager.getMVWorld(context.getIssuer().getPlayer().getWorld());
}
if (context.isOptional()) {
return null;
@@ -140,7 +177,7 @@ class MVCommandContexts extends PaperCommandContexts {
}
String worldName = context.getFirstArg();
LoadedMultiverseWorld world = worldManager.getLoadedWorld(worldName).getOrNull();
MVWorld world = worldManager.getMVWorld(worldName);
// Get world based on input, fallback to sender if input is not a world
if (resolve.equals("issuerAware")) {
@@ -149,7 +186,7 @@ class MVCommandContexts extends PaperCommandContexts {
return world;
}
if (context.getIssuer().isPlayer()) {
return worldManager.getLoadedWorld(context.getIssuer().getPlayer().getWorld()).getOrNull();
return worldManager.getMVWorld(context.getIssuer().getPlayer().getWorld());
}
if (context.isOptional()) {
return null;
@@ -162,24 +199,24 @@ class MVCommandContexts extends PaperCommandContexts {
context.popFirstArg();
return world;
}
if (context.isOptional()) {
if (!context.isOptional()) {
return null;
}
throw new InvalidCommandArgument("World " + worldName + " is not a loaded multiverse world.");
}
private LoadedMultiverseWorld[] parseLoadedMultiverseWorldArray(BukkitCommandExecutionContext context) {
private MVWorld[] parseMVWorldArray(BukkitCommandExecutionContext context) {
String resolve = context.getFlagValue("resolve", "");
LoadedMultiverseWorld playerWorld = null;
MVWorld playerWorld = null;
if (context.getIssuer().isPlayer()) {
playerWorld = worldManager.getLoadedWorld(context.getIssuer().getPlayer().getWorld()).getOrNull();
playerWorld = worldManager.getMVWorld(context.getIssuer().getPlayer().getWorld());
}
// Get world based on sender only
if (resolve.equals("issuerOnly")) {
if (playerWorld != null) {
return new LoadedMultiverseWorld[]{playerWorld};
return new MVWorld[]{playerWorld};
}
if (context.isOptional()) {
return null;
@@ -188,14 +225,14 @@ class MVCommandContexts extends PaperCommandContexts {
}
String worldStrings = context.getFirstArg();
String[] worldNames = worldStrings == null ? new String[0] : worldStrings.split(",");
Set<LoadedMultiverseWorld> worlds = new HashSet<>(worldNames.length);
String[] worldNames = worldStrings.split(",");
Set<MVWorld> worlds = new HashSet<>(worldNames.length);
for (String worldName : worldNames) {
if ("*".equals(worldName)) {
worlds.addAll(worldManager.getLoadedWorlds());
worlds.addAll(worldManager.getMVWorlds());
break;
}
LoadedMultiverseWorld world = worldManager.getLoadedWorld(worldName).getOrNull();
MVWorld world = worldManager.getMVWorld(worldName);
if (world == null) {
throw new InvalidCommandArgument("World " + worldName + " is not a loaded multiverse world.");
}
@@ -206,10 +243,10 @@ class MVCommandContexts extends PaperCommandContexts {
if (resolve.equals("issuerAware")) {
if (!worlds.isEmpty()) {
context.popFirstArg();
return worlds.toArray(new LoadedMultiverseWorld[0]);
return worlds.toArray(new MVWorld[0]);
}
if (playerWorld != null) {
return new LoadedMultiverseWorld[]{playerWorld};
return new MVWorld[]{playerWorld};
}
if (context.isOptional()) {
return null;
@@ -220,57 +257,14 @@ class MVCommandContexts extends PaperCommandContexts {
// Get world based on input only
if (!worlds.isEmpty()) {
context.popFirstArg();
return worlds.toArray(new LoadedMultiverseWorld[0]);
return worlds.toArray(new MVWorld[0]);
}
if (context.isOptional()) {
if (!context.isOptional()) {
return null;
}
throw new InvalidCommandArgument("World " + worldStrings + " is not a loaded multiverse world.");
}
private MultiverseWorld parseMultiverseWorld(BukkitCommandExecutionContext context) {
String resolve = context.getFlagValue("resolve", "");
// Get world based on sender only
if (resolve.equals("issuerOnly")) {
if (context.getIssuer().isPlayer()) {
return worldManager.getWorld(context.getIssuer().getPlayer().getWorld()).getOrNull();
}
if (context.isOptional()) {
return null;
}
throw new InvalidCommandArgument("This command can only be used by a player in a Multiverse World.");
}
String worldName = context.getFirstArg();
MultiverseWorld world = worldManager.getWorld(worldName).getOrNull();
// Get world based on input, fallback to sender if input is not a world
if (resolve.equals("issuerAware")) {
if (world != null) {
context.popFirstArg();
return world;
}
if (context.getIssuer().isPlayer()) {
return worldManager.getWorld(context.getIssuer().getPlayer().getWorld()).getOrNull();
}
if (context.isOptional()) {
return null;
}
throw new InvalidCommandArgument("Player is not in a Multiverse World.");
}
// Get world based on input only
if (world != null) {
context.popFirstArg();
return world;
}
if (context.isOptional()) {
return null;
}
throw new InvalidCommandArgument("World " + worldName + " is not a loaded multiverse world.");
}
private Player parsePlayer(BukkitCommandExecutionContext context) {
String resolve = context.getFlagValue("resolve", "");
@@ -309,7 +303,7 @@ class MVCommandContexts extends PaperCommandContexts {
context.popFirstArg();
return player;
}
if (context.isOptional()) {
if (!context.isOptional()) {
return null;
}
throw new InvalidCommandArgument("Player " + playerIdentifier + " not found.");
@@ -354,7 +348,7 @@ class MVCommandContexts extends PaperCommandContexts {
context.popFirstArg();
return players;
}
if (context.isOptional()) {
if (!context.isOptional()) {
return null;
}
throw new InvalidCommandArgument("Player " + playerIdentifier + " not found.");
@@ -0,0 +1,48 @@
package com.onarandombox.MultiverseCore.commandtools;
import co.aikar.commands.MessageType;
import co.aikar.commands.OpenBukkitCommandIssuer;
import co.aikar.locales.MessageKeyProvider;
import com.onarandombox.MultiverseCore.utils.message.Message;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class MVCommandIssuer extends OpenBukkitCommandIssuer {
private final MVCommandManager commandManager;
MVCommandIssuer(@NotNull MVCommandManager commandManager, @NotNull CommandSender sender) {
super(commandManager, sender);
this.commandManager = commandManager;
}
@Override
public MVCommandManager getManager() {
return commandManager;
}
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);
}
private void sendMessage(MessageType messageType, Message message) {
if (message instanceof MessageKeyProvider) {
sendMessage(messageType, (MessageKeyProvider) message, message.getReplacements());
} else {
var formatter = getManager().getFormat(messageType);
if (formatter != null) {
sendMessage(formatter.format(message.formatted()));
} else {
sendMessage(message.formatted());
}
}
}
}
@@ -1,14 +1,19 @@
package org.mvplugins.multiverse.core.commandtools;
package com.onarandombox.MultiverseCore.commandtools;
import java.util.List;
import co.aikar.commands.BukkitCommandCompletionContext;
import co.aikar.commands.BukkitCommandExecutionContext;
import co.aikar.commands.BukkitLocales;
import co.aikar.commands.CommandCompletions;
import co.aikar.commands.CommandContexts;
import co.aikar.commands.CommandHelp;
import co.aikar.commands.HelpEntry;
import co.aikar.commands.PaperCommandManager;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagsManager;
import com.onarandombox.MultiverseCore.commandtools.queue.CommandQueueManager;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import org.bukkit.Bukkit;
@@ -16,12 +21,6 @@ import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.MultiverseCore;
import org.mvplugins.multiverse.core.commandtools.flags.CommandFlagsManager;
import org.mvplugins.multiverse.core.commandtools.queue.CommandQueueManager;
import org.mvplugins.multiverse.core.world.WorldManager;
import org.mvplugins.multiverse.core.world.WorldNameChecker;
/**
* Main class to manage permissions.
*/
@@ -34,21 +33,21 @@ public class MVCommandManager extends PaperCommandManager {
private final Provider<MVCommandCompletions> commandCompletionsProvider;
@Inject
MVCommandManager(
public MVCommandManager(
@NotNull MultiverseCore plugin,
@NotNull CommandFlagsManager flagsManager,
@NotNull CommandQueueManager commandQueueManager,
@NotNull Provider<MVCommandContexts> commandContextsProvider,
@NotNull Provider<MVCommandCompletions> commandCompletionsProvider,
@NotNull WorldManager worldManager,
@NotNull WorldNameChecker worldNameChecker) {
@NotNull MVWorldManager worldManager
) {
super(plugin);
this.flagsManager = flagsManager;
this.commandQueueManager = commandQueueManager;
this.commandContextsProvider = commandContextsProvider;
this.commandCompletionsProvider = commandCompletionsProvider;
MVCommandConditions.load(this, worldManager, worldNameChecker);
MVCommandConditions.load(this, worldManager);
this.enableUnstableAPI("help");
}
@@ -59,12 +58,9 @@ public class MVCommandManager extends PaperCommandManager {
}
}
/**
* {@inheritDoc}
*/
@Override
public PluginLocales getLocales() {
return (PluginLocales) this.locales;
public BukkitLocales getLocales() {
return this.locales;
}
/**
@@ -0,0 +1,35 @@
package com.onarandombox.MultiverseCore.commandtools;
import co.aikar.commands.BaseCommand;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagsManager;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Contract;
@Contract
public abstract class MultiverseCommand extends BaseCommand {
protected final MVCommandManager commandManager;
private String flagGroupName;
protected MultiverseCommand(@NotNull MVCommandManager commandManager) {
this.commandManager = commandManager;
}
protected CommandFlagsManager getFlagsManager() {
return commandManager.getFlagsManager();
}
protected void registerFlagGroup(@NotNull CommandFlagGroup flagGroup) {
if (flagGroupName != null) {
throw new IllegalStateException("Flag group already registered! (name: " + flagGroupName + ")");
}
getFlagsManager().registerFlagGroup(flagGroup);
flagGroupName = flagGroup.getName();
}
protected @NotNull ParsedCommandFlags parseFlags(@NotNull String[] flags) {
return getFlagsManager().parse(flagGroupName, flags);
}
}
@@ -1,13 +1,12 @@
package org.mvplugins.multiverse.core.commandtools;
package com.onarandombox.MultiverseCore.commandtools;
import co.aikar.commands.BukkitLocales;
import com.onarandombox.MultiverseCore.utils.file.FileResClassLoader;
import jakarta.inject.Inject;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.utils.file.FileResClassLoader;
/**
* Locale manager with additional methods for loading locales from plugin's locales folder.
*/
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.commandtools.context;
package com.onarandombox.MultiverseCore.commandtools.context;
public class GameRuleValue {
private final Object value;
@@ -0,0 +1,13 @@
package com.onarandombox.MultiverseCore.commandtools.context;
public class MVConfigValue {
private final Object value;
public MVConfigValue(Object value) {
this.value = value;
}
public Object getValue() {
return value;
}
}
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.commandtools.flags;
package com.onarandombox.MultiverseCore.commandtools.flags;
import java.util.ArrayList;
import java.util.Collections;
@@ -26,12 +26,11 @@ public class CommandFlag {
/**
* Creates a new flag.
*
* @param key The key for the new flag.
* @param aliases The aliases that also refer to this flag.
* @param builder The builder.
*/
protected CommandFlag(@NotNull String key, @NotNull List<String> aliases) {
this.key = key;
this.aliases = aliases;
protected CommandFlag(@NotNull Builder<?> builder) {
key = builder.key;
aliases = builder.aliases;
}
/**
@@ -52,25 +51,14 @@ public class CommandFlag {
return aliases;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "Builder{"
+ "key='" + key + '\''
+ ", aliases=" + aliases
+ '}';
}
/**
* A builder for a flag.
*
* @param <S> The type of the builder.
*/
public static class Builder<S extends Builder<?>> {
protected final String key;
protected final List<String> aliases;
private final String key;
private final List<String> aliases;
/**
* Create a new builder.
@@ -99,7 +87,7 @@ public class CommandFlag {
* @return The flag.
*/
public @NotNull CommandFlag build(){
return new CommandFlag(key, aliases);
return new CommandFlag(this);
}
}
}
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.commandtools.flags;
package com.onarandombox.MultiverseCore.commandtools.flags;
import java.util.ArrayList;
import java.util.HashMap;
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.commandtools.flags;
package com.onarandombox.MultiverseCore.commandtools.flags;
import java.util.ArrayList;
import java.util.Collection;
@@ -60,9 +60,10 @@ public class CommandFlagsManager {
Collection<String> suggestions = new ArrayList<>();
CommandFlag currentFlag = (flags.length <= 1) ? null : flagGroup.getFlagByKey(flags[flags.length - 2]);
if (currentFlag instanceof CommandValueFlag<?> valueFlag) {
if (currentFlag instanceof CommandValueFlag) {
CommandValueFlag<?> valueFlag = (CommandValueFlag<?>) currentFlag;
if (valueFlag.getCompletion() != null) {
suggestions.addAll(valueFlag.getCompletion().apply(flags[flags.length - 1]));
suggestions.addAll(valueFlag.getCompletion().get());
}
if (valueFlag.isOptional()) {
suggestions.addAll(flagGroup.getRemainingKeys(flags));
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.commandtools.flags;
package com.onarandombox.MultiverseCore.commandtools.flags;
import co.aikar.commands.InvalidCommandArgument;
@@ -0,0 +1,172 @@
package com.onarandombox.MultiverseCore.commandtools.flags;
import java.util.Collection;
import java.util.function.Function;
import java.util.function.Supplier;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents a flag with a value.
*
* @param <T> The type of the value.
*/
public class CommandValueFlag<T> extends CommandFlag {
/**
* A builder for a flag.
*
* @param key The key for the new flag.
* @param type The type of the value.
* @return The builder.
*/
public static @NotNull <T> Builder<T, ?> builder(@NotNull String key, @NotNull Class<T> type) {
return new Builder<>(key, type);
}
private final Class<T> type;
private final boolean optional;
private final T defaultValue;
private final Function<String, T> context;
private final Supplier<Collection<String>> completion;
/**
* Creates a new flag.
*
* @param builder The builder.
*/
protected CommandValueFlag(@NotNull Builder<T, ?> builder) {
super(builder);
type = builder.type;
optional = builder.optional;
defaultValue = builder.defaultValue;
context = builder.context;
completion = builder.completion;
}
/**
* Get the type of the value.
*
* @return The type of the value.
*/
public @NotNull Class<T> getType() {
return type;
}
/**
* Check if it is optional for users to specify a value.
*
* @return True if the value is optional, false otherwise.
*/
public boolean isOptional() {
return optional;
}
/**
* Get the default value. May be null.
*
* @return The default value.
*/
public @Nullable T getDefaultValue() {
return defaultValue;
}
/**
* Get the context. May be null for {@link String} value type.
*
* @return The context.
*/
public @Nullable Function<String, T> getContext() {
return context;
}
/**
* Get the completion. May be null.
*
* @return The completion.
*/
public @Nullable Supplier<Collection<String>> getCompletion() {
return completion;
}
/**
* A builder for a flag.
*
* @param <T> The type of the value.
* @param <S> The type of the builder.
*/
public static class Builder<T, S extends Builder<T, S>> extends CommandFlag.Builder<S> {
private final Class<T> type;
private boolean optional = false;
private T defaultValue = null;
private Function<String, T> context = null;
private Supplier<Collection<String>> completion = null;
/**
* Create a new builder.
*
* @param key The key for the new flag.
* @param type The type of the value.
*/
public Builder(@NotNull String key, @NotNull Class<T> type) {
super(key);
this.type = type;
}
/**
* Set the flag as optional for users to specify a value.
*
* @return The builder.
*/
public @NotNull S optional() {
this.optional = true;
return (S) this;
}
/**
* Set the default value. Used if optional is true and user does not specify a value.
*
* @param defaultValue The default value.
* @return The builder.
*/
public @NotNull S defaultValue(@NotNull T defaultValue) {
this.defaultValue = defaultValue;
return (S) this;
}
/**
* Set the context callback for parsing string into value type.
*
* @param context The context.
* @return The builder.
*/
public @NotNull S context(@NotNull Function<String, T> context) {
this.context = context;
return (S) this;
}
/**
* Set the completion callback for autocomplete.
*
* @param completion The completion.
* @return The builder.
*/
public @NotNull S completion(@NotNull Supplier<Collection<String>> completion) {
this.completion = completion;
return (S) this;
}
/**
* Build the flag.
*
* @return The flag.
*/
@Override
public @NotNull CommandFlag build() {
if (context == null && !String.class.equals(type)) {
throw new IllegalStateException("Context is required for none-string value flags");
}
return new CommandValueFlag<>(this);
}
}
}
@@ -0,0 +1,61 @@
package com.onarandombox.MultiverseCore.commandtools.flags;
import java.util.HashMap;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Object to contain the results of the flags present and its values.
*/
public class ParsedCommandFlags
{
public static final ParsedCommandFlags EMPTY = new ParsedCommandFlags();
private final Map<String, Object> flagValues;
public ParsedCommandFlags() {
flagValues = new HashMap<>();
}
/**
* Add a flag result to the parsed flags.
*
* @param key The key of the flag.
* @param value The value of the flag.
*/
void addFlagResult(@NotNull String key, @Nullable Object value) {
flagValues.put(key, value);
}
/**
* Check if a flag is present.
*
* @param key The key of the flag.
* @return True if the flag is present, false otherwise.
*/
public boolean hasFlag(@Nullable String key) {
return this.flagValues.containsKey(key);
}
public boolean hasFlagValue(@Nullable String key) {
return flagValue(key, Object.class) != null;
}
/**
* Get the value of a flag.
*
* @param key The key of the flag.
* @return The value of the flag, null if flag does not exist or no value.
*/
public @Nullable <T> T flagValue(@Nullable String key, @NotNull Class<T> type) {
Object value = this.flagValues.get(key);
return (T) value;
}
public @NotNull <T> T flagValue(@Nullable String key, @NotNull T defaultValue, @NotNull Class<T> type) {
T value = flagValue(key, type);
return value != null ? value : defaultValue;
}
}
@@ -2,4 +2,4 @@
* This package contains all the flags parsing classes.
*
*/
package org.mvplugins.multiverse.core.commandtools.flags;
package com.onarandombox.MultiverseCore.commandtools.flags;
@@ -1,4 +1,4 @@
/**
* This package contains the classes that manages command handling.
*/
package org.mvplugins.multiverse.core.commandtools;
package com.onarandombox.MultiverseCore.commandtools;
@@ -5,12 +5,13 @@
* with this project. *
******************************************************************************/
package org.mvplugins.multiverse.core.commandtools.queue;
package com.onarandombox.MultiverseCore.commandtools.queue;
import java.util.Map;
import java.util.WeakHashMap;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import jakarta.inject.Inject;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -22,8 +23,6 @@ import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.MultiverseCore;
/**
* <p>Manages the queuing of dangerous commands that require {@code /mv confirm} before executing.</p>
*
@@ -1,7 +1,4 @@
package org.mvplugins.multiverse.core.commandtools.queue;
import java.util.Set;
import java.util.UUID;
package com.onarandombox.MultiverseCore.commandtools.queue;
import org.bukkit.Bukkit;
import org.bukkit.Server;
@@ -13,6 +10,9 @@ import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.UUID;
/**
* Used by {@link CommandQueueManager}, so different commands block can be recognised as one.
*/
@@ -5,7 +5,7 @@
* with this project. *
******************************************************************************/
package org.mvplugins.multiverse.core.commandtools.queue;
package com.onarandombox.MultiverseCore.commandtools.queue;
import co.aikar.commands.BukkitCommandIssuer;
import org.bukkit.command.CommandSender;
@@ -1,4 +1,4 @@
/**
* Manager queuing of dangerous commands in need of confirmation.
*/
package org.mvplugins.multiverse.core.commandtools.queue;
package com.onarandombox.MultiverseCore.commandtools.queue;
@@ -1,29 +1,26 @@
package org.mvplugins.multiverse.core.config;
package com.onarandombox.MultiverseCore.config;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVConfig;
import com.onarandombox.MultiverseCore.configuration.handle.CommentedYamlConfigHandle;
import com.onarandombox.MultiverseCore.configuration.migration.BooleanMigratorAction;
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
import com.onarandombox.MultiverseCore.configuration.migration.IntegerMigratorAction;
import com.onarandombox.MultiverseCore.configuration.migration.InvertBoolMigratorAction;
import com.onarandombox.MultiverseCore.configuration.migration.MoveMigratorAction;
import com.onarandombox.MultiverseCore.configuration.migration.VersionMigrator;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import io.vavr.control.Try;
import jakarta.inject.Inject;
import org.bukkit.plugin.PluginManager;
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.api.MVConfig;
import org.mvplugins.multiverse.core.configuration.handle.CommentedYamlConfigHandle;
import org.mvplugins.multiverse.core.configuration.handle.StringPropertyHandle;
import org.mvplugins.multiverse.core.configuration.migration.BooleanMigratorAction;
import org.mvplugins.multiverse.core.configuration.migration.ConfigMigrator;
import org.mvplugins.multiverse.core.configuration.migration.IntegerMigratorAction;
import org.mvplugins.multiverse.core.configuration.migration.InvertBoolMigratorAction;
import org.mvplugins.multiverse.core.configuration.migration.MoveMigratorAction;
import org.mvplugins.multiverse.core.configuration.migration.VersionMigrator;
@Service
public class MVCoreConfig implements MVConfig {
public static final String CONFIG_FILENAME = "config.yml";
@@ -32,14 +29,14 @@ public class MVCoreConfig implements MVConfig {
private final Path configPath;
private final MVCoreConfigNodes configNodes;
private final CommentedYamlConfigHandle configHandle;
private final StringPropertyHandle stringPropertyHandle;
@Inject
MVCoreConfig(@NotNull MultiverseCore core, @NotNull PluginManager pluginManager) {
this.configPath = Path.of(core.getDataFolder().getPath(), CONFIG_FILENAME);
this.configNodes = new MVCoreConfigNodes(pluginManager);
this.configHandle = CommentedYamlConfigHandle.builder(configPath, configNodes.getNodes())
this.configHandle = CommentedYamlConfigHandle.builder(configPath)
.logger(Logging.getLogger())
.nodes(configNodes.getNodes())
.migrator(ConfigMigrator.builder(configNodes.VERSION)
.addVersionMigrator(VersionMigrator.builder(5.0)
.addAction(MoveMigratorAction.of("multiverse-configuration.enforceaccess", "world.enforce-access"))
@@ -70,7 +67,7 @@ public class MVCoreConfig implements MVConfig {
.build())
.build())
.build();
this.stringPropertyHandle = new StringPropertyHandle(configHandle);
load();
save();
}
@@ -92,7 +89,7 @@ public class MVCoreConfig implements MVConfig {
}
@Override
public Try<Void> load() {
public boolean load() {
migrateFromOldConfigFile();
return configHandle.load();
}
@@ -103,13 +100,24 @@ public class MVCoreConfig implements MVConfig {
}
@Override
public Try<Void> save() {
return configHandle.save();
public boolean save() {
configHandle.save();
return true;
}
@Override
public StringPropertyHandle getStringPropertyHandle() {
return stringPropertyHandle;
public NodeGroup getNodes() {
return configNodes.getNodes();
}
@Override
public Try<Object> getProperty(String name) {
return configHandle.get(name);
}
@Override
public Try<Void> setProperty(String name, Object value) {
return configHandle.set(name, value);
}
@Override
@@ -172,30 +180,6 @@ public class MVCoreConfig implements MVConfig {
return configHandle.get(configNodes.FIRST_SPAWN_LOCATION);
}
@Override
public void setEnableJoinDestination(boolean enableJoinDestination) {
configHandle.set(configNodes.ENABLE_JOIN_DESTINATION, enableJoinDestination);
}
@Override
public boolean getEnableJoinDestination() {
return configHandle.get(configNodes.ENABLE_JOIN_DESTINATION);
}
@Override
public void setJoinDestination(String alwaysSpawnDestination) {
configHandle.set(configNodes.JOIN_DESTINATION, alwaysSpawnDestination);
}
@Override
@Nullable
public String getJoinDestination() {
if (Objects.equals(configHandle.get(configNodes.JOIN_DESTINATION), "")) {
return null;
}
return configHandle.get(configNodes.JOIN_DESTINATION);
}
@Override
public void setUseCustomPortalSearch(boolean useDefaultPortalSearch) {
configHandle.set(configNodes.USE_CUSTOM_PORTAL_SEARCH, useDefaultPortalSearch);
@@ -1,16 +1,16 @@
package org.mvplugins.multiverse.core.config;
package com.onarandombox.MultiverseCore.config;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.configuration.node.ConfigHeaderNode;
import com.onarandombox.MultiverseCore.configuration.node.ConfigNode;
import com.onarandombox.MultiverseCore.configuration.node.Node;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import com.onarandombox.MultiverseCore.event.MVDebugModeEvent;
import com.onarandombox.MultiverseCore.exceptions.MultiverseException;
import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode;
import io.vavr.control.Try;
import org.bukkit.plugin.PluginManager;
import org.mvplugins.multiverse.core.configuration.node.ConfigHeaderNode;
import org.mvplugins.multiverse.core.configuration.node.ConfigNode;
import org.mvplugins.multiverse.core.configuration.node.Node;
import org.mvplugins.multiverse.core.configuration.node.NodeGroup;
import org.mvplugins.multiverse.core.event.MVDebugModeEvent;
import org.mvplugins.multiverse.core.exceptions.MultiverseException;
class MVCoreConfigNodes {
private final NodeGroup nodes = new NodeGroup();
@@ -29,15 +29,7 @@ class MVCoreConfigNodes {
return node;
}
// BEGIN CHECKSTYLE-SUPPRESSION: Javadoc
// BEGIN CHECKSTYLE-SUPPRESSION: MemberName
// BEGIN CHECKSTYLE-SUPPRESSION: Abbreviation
// BEGIN CHECKSTYLE-SUPPRESSION: VisibilityModifier
// BEGIN CHECKSTYLE-SUPPRESSION: MultipleStringLiterals
// BEGIN CHECKSTYLE-SUPPRESSION: LineLength
// TODO: hacky way to get the header to the top of the file
private final ConfigHeaderNode HEADER = node(ConfigHeaderNode.builder("world")
private final ConfigHeaderNode HEADER = node(ConfigHeaderNode.builder("world") // TODO hacky way to get the header to the top of the file
.comment("####################################################################################################")
.comment("# #")
.comment("# █▀▄▀█ █░█ █░░ ▀█▀ █ █░█ █▀▀ █▀█ █▀ █▀▀   █▀▀ █▀█ █▀█ █▀▀ #")
@@ -61,12 +53,12 @@ class MVCoreConfigNodes {
.comment("")
.build());
//private final ConfigHeaderNode WORLD_HEADER = node(ConfigHeaderNode.builder("world")
// .comment("")
// .comment("")
// .build());
// private final ConfigHeaderNode WORLD_HEADER = node(ConfigHeaderNode.builder("world")
// .comment("")
// .comment("")
// .build());
final ConfigNode<Boolean> ENFORCE_ACCESS = node(ConfigNode.builder("world.enforce-access", Boolean.class)
public final ConfigNode<Boolean> ENFORCE_ACCESS = node(ConfigNode.builder("world.enforce-access", Boolean.class)
.comment("This setting will prevent players from entering worlds they don't have access to.")
.comment("If this is set to false, players will be able to enter any world they want.")
.comment("If this is set to true, players will only be able to enter worlds they have")
@@ -75,7 +67,7 @@ class MVCoreConfigNodes {
.name("enforce-access")
.build());
final ConfigNode<Boolean> ENFORCE_GAMEMODE = node(ConfigNode.builder("world.enforce-gamemode", Boolean.class)
public final ConfigNode<Boolean> ENFORCE_GAMEMODE = node(ConfigNode.builder("world.enforce-gamemode", Boolean.class)
.comment("")
.comment("Sets whether Multiverse will should enforce gamemode on world change.")
.comment("If enabled, players will be forced into the gamemode of the world they are entering, unless they have")
@@ -84,14 +76,14 @@ class MVCoreConfigNodes {
.name("enforce-gamemode")
.build());
final ConfigNode<Boolean> AUTO_PURGE_ENTITIES = node(ConfigNode.builder("world.auto-purge-entities", Boolean.class)
public final ConfigNode<Boolean> AUTO_PURGE_ENTITIES = node(ConfigNode.builder("world.auto-purge-entities", Boolean.class)
.comment("")
.comment("Sets whether Multiverse will purge mobs and entities with be automatically.")
.defaultValue(false)
.name("auto-purge-entities")
.build());
final ConfigNode<Boolean> TELEPORT_INTERCEPT = node(ConfigNode.builder("world.teleport-intercept", Boolean.class)
public final ConfigNode<Boolean> TELEPORT_INTERCEPT = node(ConfigNode.builder("world.teleport-intercept", Boolean.class)
.comment("")
.comment("If this is set to true, Multiverse will enforce access permissions for all teleportation,")
.comment("including teleportation from other plugins.")
@@ -104,7 +96,7 @@ class MVCoreConfigNodes {
.comment("")
.build());
final ConfigNode<Boolean> FIRST_SPAWN_OVERRIDE = node(ConfigNode.builder("spawn.first-spawn-override", Boolean.class)
public final ConfigNode<Boolean> FIRST_SPAWN_OVERRIDE = node(ConfigNode.builder("spawn.first-spawn-override", Boolean.class)
.comment("Sets whether Multiverse will override the first spawn location of a world.")
.comment("If enabled, Multiverse will set the first spawn location of a world to the spawn location of the world.")
.comment("If disabled, it will default to server.properties settings.")
@@ -112,7 +104,7 @@ class MVCoreConfigNodes {
.name("first-spawn-override")
.build());
final ConfigNode<String> FIRST_SPAWN_LOCATION = node(ConfigNode.builder("spawn.first-spawn-location", String.class)
public final ConfigNode<String> FIRST_SPAWN_LOCATION = node(ConfigNode.builder("spawn.first-spawn-location", String.class)
.comment("")
.comment("Sets the world that Multiverse will use as the location for players that first join the server.")
.comment("This only applies if first-spawn-override is set to true.")
@@ -120,34 +112,19 @@ class MVCoreConfigNodes {
.name("first-spawn-location")
.build());
final ConfigNode<Boolean> ENABLE_JOIN_DESTINATION = node(ConfigNode.builder("spawn.enable-join-destination", Boolean.class)
.comment("")
.comment("Enables join-destination below.")
.defaultValue(false)
.name("enable-join-destination")
.build());
final ConfigNode<String> JOIN_DESTINATION = node(ConfigNode.builder("spawn.join-destination", String.class)
.comment("")
.comment("Sets the destination that Multiverse will use to spawn players on every login")
.comment("Set the above enable-join-destination to false to disable")
.defaultValue("")
.name("join-destination")
.build());
private final ConfigHeaderNode PORTAL_HEADER = node(ConfigHeaderNode.builder("portal")
.comment("")
.comment("")
.build());
final ConfigNode<Boolean> USE_CUSTOM_PORTAL_SEARCH = node(ConfigNode.builder("portal.use-custom-portal-search", Boolean.class)
public final ConfigNode<Boolean> USE_CUSTOM_PORTAL_SEARCH = node(ConfigNode.builder("portal.use-custom-portal-search", Boolean.class)
.comment("This config option defines whether or not Multiverse should interfere with's Bukkit's default portal search radius.")
.comment("Setting it to false would mean you want to simply let Bukkit decides the search radius itself.")
.defaultValue(false)
.name("use-custom-portal-search")
.build());
final ConfigNode<Integer> CUSTOM_PORTAL_SEARCH_RADIUS = node(ConfigNode.builder("portal.custom-portal-search-radius", Integer.class)
public final ConfigNode<Integer> CUSTOM_PORTAL_SEARCH_RADIUS = node(ConfigNode.builder("portal.custom-portal-search-radius", Integer.class)
.comment("")
.comment("This config option defines the search radius Multiverse should use when searching for a portal.")
.comment("This only applies if use-custom-portal-search is set to true.")
@@ -163,14 +140,14 @@ class MVCoreConfigNodes {
.comment("")
.build());
final ConfigNode<Boolean> ENABLE_CHAT_PREFIX = node(ConfigNode.builder("messaging.enable-chat-prefix", Boolean.class)
public final ConfigNode<Boolean> ENABLE_CHAT_PREFIX = node(ConfigNode.builder("messaging.enable-chat-prefix", Boolean.class)
.comment("This config option defines whether or not Multiverse should prefix the chat with the world name.")
.comment("This only applies if use-custom-portal-search is set to true.")
.defaultValue(false)
.name("enable-chat-prefix")
.build());
final ConfigNode<String> CHAT_PREFIX_FORMAT = node(ConfigNode.builder("messaging.chat-prefix-format", String.class)
public final ConfigNode<String> CHAT_PREFIX_FORMAT = node(ConfigNode.builder("messaging.chat-prefix-format", String.class)
.comment("")
.comment("This config option defines the format Multiverse should use when prefixing the chat with the world name.")
.comment("This only applies if enable-chat-prefix is set to true.")
@@ -178,7 +155,7 @@ class MVCoreConfigNodes {
.name("chat-prefix-format")
.build());
final ConfigNode<Boolean> REGISTER_PAPI_HOOK = node(ConfigNode.builder("messaging.register-papi-hook", Boolean.class)
public final ConfigNode<Boolean> REGISTER_PAPI_HOOK = node(ConfigNode.builder("messaging.register-papi-hook", Boolean.class)
.comment("")
.comment("This config option defines whether or not Multiverse should register the PlaceholderAPI hook.")
.comment("This only applies if PlaceholderAPI is installed.")
@@ -191,7 +168,7 @@ class MVCoreConfigNodes {
.comment("")
.build());
final ConfigNode<Integer> GLOBAL_DEBUG = node(ConfigNode.builder("misc.global-debug", Integer.class)
public final ConfigNode<Integer> GLOBAL_DEBUG = node(ConfigNode.builder("misc.global-debug", Integer.class)
.comment("This is our debug flag to help identify issues with Multiverse.")
.comment("If you are having issues with Multiverse, please set this to 3 and then post your log to pastebin.com")
.comment("Otherwise, there's no need to touch this. If not instructed by a wiki page or developer.")
@@ -213,7 +190,7 @@ class MVCoreConfigNodes {
})
.build());
final ConfigNode<Boolean> SILENT_START = node(ConfigNode.builder("misc.silent-start", Boolean.class)
public final ConfigNode<Boolean> SILENT_START = node(ConfigNode.builder("misc.silent-start", Boolean.class)
.comment("")
.comment("If true, the startup console messages will no longer show.")
.defaultValue(false)
@@ -221,14 +198,14 @@ class MVCoreConfigNodes {
.onSetValue((oldValue, newValue) -> Logging.setShowingConfig(!newValue))
.build());
final ConfigNode<Boolean> SHOW_DONATION_MESSAGE = node(ConfigNode.builder("misc.show-donation-message", Boolean.class)
public final ConfigNode<Boolean> SHOW_DONATION_MESSAGE = node(ConfigNode.builder("misc.show-donation-message", Boolean.class)
.comment("")
.comment("If you don't want to donate, you can set this to false and Multiverse will stop nagging you.")
.defaultValue(true)
.name("show-donation-message")
.build());
final ConfigNode<Double> VERSION = node(ConfigNode.builder("version", Double.class)
public final ConfigNode<Double> VERSION = node(ConfigNode.builder("version", Double.class)
.comment("")
.comment("")
.comment("This just signifies the version number so we can see what version of config you have.")
@@ -236,11 +213,4 @@ class MVCoreConfigNodes {
.defaultValue(MVCoreConfig.CONFIG_VERSION)
.name(null)
.build());
// END CHECKSTYLE-SUPPRESSION: Javadoc
// END CHECKSTYLE-SUPPRESSION: MemberName
// END CHECKSTYLE-SUPPRESSION: Abbreviation
// END CHECKSTYLE-SUPPRESSION: VisibilityModifier
// END CHECKSTYLE-SUPPRESSION: MultipleStringLiterals
// END CHECKSTYLE-SUPPRESSION: LineLength
}
@@ -1,20 +1,17 @@
package org.mvplugins.multiverse.core.configuration.handle;
package com.onarandombox.MultiverseCore.configuration.handle;
import java.io.IOException;
import java.nio.file.Path;
import java.util.logging.Logger;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import com.onarandombox.MultiverseCore.configuration.node.CommentedNode;
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
import io.github.townyadvanced.commentedconfiguration.CommentedConfiguration;
import io.vavr.control.Try;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.mvplugins.multiverse.core.configuration.migration.ConfigMigrator;
import org.mvplugins.multiverse.core.configuration.node.CommentedNode;
import org.mvplugins.multiverse.core.configuration.node.NodeGroup;
import org.mvplugins.multiverse.core.configuration.node.ValueNode;
/**
* Configuration handle for commented YAML files.
*/
@@ -24,18 +21,13 @@ public class CommentedYamlConfigHandle extends FileConfigHandle<CommentedConfigu
* Creates a new builder for a {@link CommentedYamlConfigHandle}.
*
* @param configPath The path to the config file.
* @param nodes The nodes.
* @return The builder.
*/
public static @NotNull Builder builder(@NotNull Path configPath, @NotNull NodeGroup nodes) {
return new Builder(configPath, nodes);
public static @NotNull Builder builder(@NotNull Path configPath) {
return new Builder(configPath);
}
protected CommentedYamlConfigHandle(
@NotNull Path configPath,
@Nullable Logger logger,
@NotNull NodeGroup nodes,
@Nullable ConfigMigrator migrator) {
protected CommentedYamlConfigHandle(@NotNull Path configPath, @Nullable Logger logger, @Nullable NodeGroup nodes, @Nullable ConfigMigrator migrator) {
super(configPath, logger, nodes, migrator);
}
@@ -43,12 +35,9 @@ public class CommentedYamlConfigHandle extends FileConfigHandle<CommentedConfigu
* {@inheritDoc}
*/
@Override
protected void loadConfigObject() throws IOException {
protected boolean loadConfigObject() {
config = new CommentedConfiguration(configPath, logger);
if (!config.load()) {
throw new IOException("Failed to load commented config file " + configPath
+ ". See console for details.");
}
return config.load();
}
/**
@@ -70,15 +59,10 @@ public class CommentedYamlConfigHandle extends FileConfigHandle<CommentedConfigu
}
}
if (node instanceof ValueNode valueNode) {
//noinspection unchecked
set(valueNode, oldConfig.getObject(
valueNode.getPath(),
valueNode.getType(),
valueNode.getDefaultValue())).onFailure(e -> {
Logging.warning("Failed to set node " + valueNode.getPath()
+ " to " + valueNode.getDefaultValue());
reset(valueNode);
});
set(valueNode, oldConfig.getObject(valueNode.getPath(), valueNode.getType(), valueNode.getDefaultValue())).onFailure(e -> {
Logging.warning("Failed to set node " + valueNode.getPath() + " to " + valueNode.getDefaultValue());
setDefault(valueNode);
});
}
});
}
@@ -87,18 +71,15 @@ public class CommentedYamlConfigHandle extends FileConfigHandle<CommentedConfigu
* {@inheritDoc}
*/
@Override
public Try<Void> save() {
// TODO: There is no way to check if the save was successful.
return Try.run(() -> config.save());
public boolean save() {
config.save();
return true;
}
/**
* Builder for {@link CommentedYamlConfigHandle}.
*/
public static class Builder extends FileConfigHandle.Builder<CommentedConfiguration, Builder> {
protected Builder(@NotNull Path configPath, @NotNull NodeGroup nodes) {
super(configPath, nodes);
protected Builder(@NotNull Path configPath) {
super(configPath);
}
/**
@@ -0,0 +1,47 @@
package com.onarandombox.MultiverseCore.configuration.handle;
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.logging.Logger;
/**
* Configuration handle for a single configuration section.
*/
public class ConfigurationSectionHandle extends GenericConfigHandle<ConfigurationSection> {
public static Builder<? extends Builder> builder(@NotNull ConfigurationSection configurationSection) {
return new Builder<>(configurationSection);
}
public ConfigurationSectionHandle(@NotNull ConfigurationSection configurationSection,
@Nullable Logger logger,
@Nullable NodeGroup nodes,
@Nullable ConfigMigrator migrator) {
super(logger, nodes, migrator);
this.config = configurationSection;
}
/**
* Builder for {@link ConfigurationSectionHandle}.
*
* @param <B> The builder type.
*/
public static class Builder<B extends Builder<B>> extends GenericConfigHandle.Builder<ConfigurationSection, B> {
private final ConfigurationSection configurationSection;
protected Builder(@NotNull ConfigurationSection configurationSection) {
this.configurationSection = configurationSection;
}
/**
* {@inheritDoc}
*/
@Override
public @NotNull ConfigurationSectionHandle build() {
return new ConfigurationSectionHandle(configurationSection, logger, nodes, migrator);
}
}
}
@@ -0,0 +1,130 @@
package com.onarandombox.MultiverseCore.configuration.handle;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.logging.Logger;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Generic configuration handle for file based configurations.
* @param <C> The configuration type.
*/
abstract class FileConfigHandle<C extends FileConfiguration> extends GenericConfigHandle<C> {
protected final @NotNull Path configPath;
protected final @NotNull File configFile;
protected FileConfigHandle(@NotNull Path configPath, @Nullable Logger logger, @Nullable NodeGroup nodes, @Nullable ConfigMigrator migrator) {
super(logger, nodes, migrator);
this.configPath = configPath;
this.configFile = configPath.toFile();
}
/**
* {@inheritDoc}
*/
@Override
public boolean load() {
if (!createConfigFile()) {
Logging.severe("Failed to create config file: %s", configFile.getName());
return false;
}
if (!loadConfigObject()) {
Logging.severe("Failed to load config file: %s", configFile.getName());
return false;
}
migrateConfig();
setUpNodes();
return true;
}
/**
* Create a new config file if file does not exist
*
* @return True if file exist or created successfully, otherwise false.
*/
protected boolean createConfigFile() {
if (configFile.exists()) {
return true;
}
try {
if (!configFile.createNewFile()) {
return false;
}
Logging.info("Created new config file: %s", configFile.getName());
} catch (IOException e) {
return false;
}
return true;
}
/**
* Loads the configuration object.
*
* @return True if the configuration was loaded successfully, false otherwise.
*/
protected abstract boolean loadConfigObject();
/**
* Saves the configuration.
*/
public abstract boolean save();
/**
* Checks if the configuration is loaded.
*
* @return True if the configuration is loaded, false otherwise.
*/
public boolean isLoaded() {
return config != null;
}
/**
* Gets the configuration.
*
* @return The configuration.
*/
public C getConfig() {
return config;
}
/**
* Abstract builder for {@link FileConfigHandle}.
*
* @param <C> The configuration type.
* @param <B> The builder type.
*/
public static abstract class Builder<C extends FileConfiguration, B extends Builder<C, B>> extends GenericConfigHandle.Builder<C, B> {
protected @NotNull Path configPath;
protected @Nullable Logger logger;
protected @Nullable NodeGroup nodes;
protected @Nullable ConfigMigrator migrator;
protected Builder(@NotNull Path configPath) {
this.configPath = configPath;
}
/**
* Builds the configuration handle.
*
* @return The configuration handle.
*/
public abstract @NotNull FileConfigHandle<C> build();
@SuppressWarnings("unchecked")
protected B self() {
return (B) this;
}
}
}
@@ -0,0 +1,196 @@
package com.onarandombox.MultiverseCore.configuration.handle;
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
import com.onarandombox.MultiverseCore.configuration.node.ConfigNodeNotFoundException;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
import io.vavr.control.Try;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.logging.Logger;
/**
* Generic configuration handle for all ConfigurationSection types.
*/
public abstract class GenericConfigHandle<C extends ConfigurationSection> {
protected final @Nullable Logger logger;
protected final @Nullable NodeGroup nodes;
protected final @Nullable ConfigMigrator migrator;
protected C config;
public GenericConfigHandle(@Nullable Logger logger, @Nullable NodeGroup nodes, @Nullable ConfigMigrator migrator) {
this.logger = logger;
this.nodes = nodes;
this.migrator = migrator;
}
/**
* Loads the configuration.
*
* @return True if the configuration was loaded successfully, false otherwise.
*/
public boolean load() {
migrateConfig();
setUpNodes();
return true;
}
/**
* Migrates the configuration.
*/
protected void migrateConfig() {
if (migrator != null) {
migrator.migrate(config);
}
}
/**
* Sets up the nodes.
*/
protected void setUpNodes() {
if (nodes == null || nodes.isEmpty()) {
return;
}
nodes.forEach(node -> {
if (node instanceof ValueNode valueNode) {
set(valueNode, config.getObject(valueNode.getPath(), valueNode.getType(), valueNode.getDefaultValue()));
}
});
}
/**
* Gets the value of a node, if the node has a default value, it will be returned if the node is not found.
* @param name The name of the node.
* @return The value of the node.
*/
public Try<Object> get(@Nullable String name) {
return nodes.findNode(name, ValueNode.class)
.toTry(() -> new ConfigNodeNotFoundException(name))
.map(node -> get((ValueNode<Object>) node));
}
/**
* Gets the value of a node, if the node has a default value, it will be returned if the node is not found.
*
* @param node The node to get the value of.
* @return The value of the node.
*/
public <T> T get(@NotNull ValueNode<T> node) {
return config.getObject(node.getPath(), node.getType(), node.getDefaultValue());
}
/**
* Sets the value of a node, if the validator is not null, it will be tested first.
*
* @param name The name of the node.
* @param value The value to set.
* @return True if the value was set, false otherwise.
*/
public Try<Void> set(@Nullable String name, Object value) {
return nodes.findNode(name, ValueNode.class)
.toTry(() -> new ConfigNodeNotFoundException(name))
.flatMap(node -> set(node, value));
}
/**
* Sets the value of a node, if the validator is not null, it will be tested first.
*
* @param node The node to set the value of.
* @param value The value to set.
* @return True if the value was set, false otherwise.
* @param <T> The type of the node value.
*/
public <T> Try<Void> set(@NotNull ValueNode<T> node, T value) {
return node.validate(value).map(ignore -> {
T oldValue = get(node);
config.set(node.getPath(), value);
node.onSetValue(oldValue, get(node));
return null;
});
}
/**
* Sets the default value of a node.
*
* @param node The node to set the default value of.
*/
public void setDefault(@NotNull ValueNode node) {
config.set(node.getPath(), node.getDefaultValue());
}
/**
* Abstract builder for {@link GenericConfigHandle}.
*
* @param <C> The configuration type.
* @param <B> The builder type.
*/
public static abstract class Builder<C extends ConfigurationSection, B extends GenericConfigHandle.Builder<C, B>> {
protected @Nullable Logger logger;
protected @Nullable NodeGroup nodes;
protected @Nullable ConfigMigrator migrator;
protected Builder() {}
/**
* Sets the logger.
*
* @param logger The logger.
* @return The builder.
*/
public B logger(@Nullable Logger logger) {
this.logger = logger;
return self();
}
/**
* Sets the logger.
*
* @param plugin The plugin to get the logger from.
* @return The builder.
*/
public B logger(Plugin plugin) {
this.logger = plugin.getLogger();
return self();
}
/**
* Sets the nodes.
*
* @param nodes The nodes.
* @return The builder.
*/
public B nodes(@Nullable NodeGroup nodes) {
this.nodes = nodes;
return self();
}
/**
* Sets the migrator.
*
* @param migrator The migrator.
* @return The builder.
*/
public B migrator(@Nullable ConfigMigrator migrator) {
this.migrator = migrator;
return self();
}
/**
* Builds the configuration handle.
*
* @return The configuration handle.
*/
public abstract @NotNull GenericConfigHandle<C> build();
@SuppressWarnings("unchecked")
protected B self() {
return (B) this;
}
}
}
@@ -1,18 +1,17 @@
package org.mvplugins.multiverse.core.configuration.handle;
package com.onarandombox.MultiverseCore.configuration.handle;
import java.io.IOException;
import java.nio.file.Path;
import java.util.logging.Logger;
import io.vavr.control.Try;
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.mvplugins.multiverse.core.configuration.migration.ConfigMigrator;
import org.mvplugins.multiverse.core.configuration.node.NodeGroup;
/**
* Configuration handle for YAML files.
*/
@@ -22,18 +21,13 @@ public class YamlConfigHandle extends FileConfigHandle<YamlConfiguration> {
* Creates a new builder for {@link YamlConfigHandle}.
*
* @param configPath The path to the config file.
* @param nodes The nodes.
* @return The builder.
*/
public static @NotNull Builder<? extends Builder> builder(@NotNull Path configPath, @NotNull NodeGroup nodes) {
return new Builder<>(configPath, nodes);
public static @NotNull Builder<? extends Builder> builder(@NotNull Path configPath) {
return new Builder<>(configPath);
}
protected YamlConfigHandle(
@NotNull Path configPath,
@Nullable Logger logger,
@NotNull NodeGroup nodes,
@Nullable ConfigMigrator migrator) {
protected YamlConfigHandle(@NotNull Path configPath, @Nullable Logger logger, @Nullable NodeGroup nodes, @Nullable ConfigMigrator migrator) {
super(configPath, logger, nodes, migrator);
}
@@ -41,28 +35,37 @@ public class YamlConfigHandle extends FileConfigHandle<YamlConfiguration> {
* {@inheritDoc}
*/
@Override
protected void loadConfigObject() throws IOException, InvalidConfigurationException {
protected boolean loadConfigObject() {
config = new YamlConfiguration();
config.load(configFile);
try {
config.load(configFile);
} catch (IOException | InvalidConfigurationException e) {
return false;
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public Try<Void> save() {
return Try.run(() -> config.save(configFile));
public boolean save() {
try {
config.save(configFile);
} catch (IOException e) {
return false;
}
return true;
}
/**
* Builder for {@link YamlConfigHandle}.
*
* @param <B> The type of the builder.
*/
public static class Builder<B extends Builder<B>> extends FileConfigHandle.Builder<YamlConfiguration, B> {
protected Builder(@NotNull Path configPath, @NotNull NodeGroup nodes) {
super(configPath, nodes);
protected Builder(@NotNull Path configPath) {
super(configPath);
}
/**
@@ -1,8 +1,9 @@
package org.mvplugins.multiverse.core.configuration.migration;
package com.onarandombox.MultiverseCore.configuration.migration;
import co.aikar.commands.ACFUtil;
import com.dumptruckman.minecraft.util.Logging;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
/**
* Single migrator action that converts a string value to a boolean.
@@ -1,12 +1,13 @@
package org.mvplugins.multiverse.core.configuration.migration;
package com.onarandombox.MultiverseCore.configuration.migration;
import java.util.ArrayList;
import java.util.List;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
import io.github.townyadvanced.commentedconfiguration.setting.TypedValueNode;
import org.bukkit.configuration.ConfigurationSection;
import org.mvplugins.multiverse.core.configuration.node.ValueNode;
import org.bukkit.configuration.file.FileConfiguration;
/**
* Helper class for migrating configs to the latest config version.
@@ -1,8 +1,9 @@
package org.mvplugins.multiverse.core.configuration.migration;
package com.onarandombox.MultiverseCore.configuration.migration;
import co.aikar.commands.ACFUtil;
import com.dumptruckman.minecraft.util.Logging;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
/**
* Single migrator action that converts a string value to an integer.
@@ -1,7 +1,8 @@
package org.mvplugins.multiverse.core.configuration.migration;
package com.onarandombox.MultiverseCore.configuration.migration;
import com.dumptruckman.minecraft.util.Logging;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
/**
* Single migrator action that inverts a boolean value for a given path.
@@ -1,6 +1,7 @@
package org.mvplugins.multiverse.core.configuration.migration;
package com.onarandombox.MultiverseCore.configuration.migration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
/**
* A migrator action is a single action that is performed when migrating a config.
@@ -1,9 +1,10 @@
package org.mvplugins.multiverse.core.configuration.migration;
package com.onarandombox.MultiverseCore.configuration.migration;
import java.util.Optional;
import com.dumptruckman.minecraft.util.Logging;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
/**
* Single migrator action that moves a value from one path to another.
@@ -36,8 +37,8 @@ public class MoveMigratorAction implements MigratorAction {
public void migrate(ConfigurationSection config) {
Optional.ofNullable(config.get(fromPath))
.ifPresent(value -> {
config.set(fromPath, null);
config.set(toPath, value);
config.set(fromPath, null);
Logging.config("Moved path %s to %s", fromPath, toPath);
});
}
@@ -1,9 +1,10 @@
package org.mvplugins.multiverse.core.configuration.migration;
package com.onarandombox.MultiverseCore.configuration.migration;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
/**
* A version migrator is a collection of migrator actions that are performed when migrating a config to a specific version.
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.configuration.node;
package com.onarandombox.MultiverseCore.configuration.node;
import org.jetbrains.annotations.NotNull;
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.configuration.node;
package com.onarandombox.MultiverseCore.configuration.node;
import java.util.ArrayList;
import java.util.List;
@@ -0,0 +1,172 @@
package com.onarandombox.MultiverseCore.configuration.node;
import java.util.function.BiConsumer;
import java.util.function.Function;
import io.vavr.control.Option;
import io.vavr.control.Try;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A node that contains a value.
* @param <T> The type of the value.
*/
public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
/**
* Creates a new builder for a {@link ConfigNode}.
*
* @param path The path of the node.
* @param type The type of the value.
* @return The new builder.
* @param <T> The type of the value.
*/
public static @NotNull <T> ConfigNode.Builder<T, ? extends ConfigNode.Builder<T, ?>> builder(
@NotNull String path,
@NotNull Class<T> type
) {
return new ConfigNode.Builder<>(path, type);
}
protected final @Nullable String name;
protected final @NotNull Class<T> type;
protected final @Nullable T defaultValue;
protected final @Nullable Function<T, Try<Void>> validator;
protected final @Nullable BiConsumer<T, T> onSetValue;
protected ConfigNode(
@NotNull String path,
@NotNull String[] comments,
@Nullable String name,
@NotNull Class<T> type,
@Nullable T defaultValue,
@Nullable Function<T, Try<Void>> validator,
@Nullable BiConsumer<T, T> onSetValue
) {
super(path, comments);
this.name = name;
this.type = type;
this.defaultValue = defaultValue;
this.validator = validator;
this.onSetValue = onSetValue;
}
/**
* {@inheritDoc}
*/
@Override
public @NotNull Option<String> getName() {
return Option.of(name);
}
/**
* {@inheritDoc}
*/
@Override
public @NotNull Class<T> getType() {
return type;
}
/**
* {@inheritDoc}
*/
@Override
public @Nullable T getDefaultValue() {
return defaultValue;
}
/**
* {@inheritDoc}
*/
@Override
public Try<Void> validate(@Nullable T value) {
if (validator != null) {
return validator.apply(value);
}
return Try.success(null);
}
/**
* {@inheritDoc}
*/
@Override
public void onSetValue(@Nullable T oldValue, @Nullable T newValue) {
if (onSetValue != null) {
onSetValue.accept(oldValue, newValue);
}
}
/**
* Builder for {@link ConfigNode}.
*
* @param <T> The type of the value.
* @param <B> The type of the builder.
*/
public static class Builder<T, B extends ConfigNode.Builder<T, B>> extends ConfigHeaderNode.Builder<B> {
protected @Nullable String name;
protected @NotNull final Class<T> type;
protected @Nullable T defaultValue;
protected @Nullable Function<T, Try<Void>> validator;
protected @Nullable BiConsumer<T, T> onSetValue;
/**
* Creates a new builder.
*
* @param path The path of the node.
* @param type The type of the value.
*/
protected Builder(@NotNull String path, @NotNull Class<T> type) {
super(path);
this.name = path;
this.type = type;
}
/**
* Sets the default value for this node.
*
* @param defaultValue The default value.
* @return This builder.
*/
public @NotNull B defaultValue(@NotNull T defaultValue) {
this.defaultValue = defaultValue;
return (B) this;
}
/**
* Sets the name of this node. Used for identifying the node from user input.
*
* @param name The name of this node.
* @return This builder.
*/
public @NotNull B name(@Nullable String name) {
this.name = name;
return (B) this;
}
public @NotNull B validator(@NotNull Function<T, Try<Void>> validator) {
this.validator = validator;
return (B) this;
}
/**
* Sets the action to be performed when the value is set.
*
* @param onSetValue The action to be performed.
* @return This builder.
*/
public @NotNull B onSetValue(@NotNull BiConsumer<T, T> onSetValue) {
this.onSetValue = onSetValue;
return (B) this;
}
/**
* {@inheritDoc}
*/
@Override
public @NotNull ConfigNode<T> build() {
return new ConfigNode<>(path, comments.toArray(new String[0]), name, type, defaultValue, validator, onSetValue);
}
}
}
@@ -1,11 +1,10 @@
package org.mvplugins.multiverse.core.configuration.node;
package com.onarandombox.MultiverseCore.configuration.node;
import com.onarandombox.MultiverseCore.exceptions.MultiverseException;
import org.jetbrains.annotations.Nullable;
import org.mvplugins.multiverse.core.exceptions.MultiverseException;
import static org.mvplugins.multiverse.core.utils.MVCorei18n.CONFIG_NODE_NOTFOUND;
import static org.mvplugins.multiverse.core.utils.message.MessageReplacement.replace;
import static com.onarandombox.MultiverseCore.utils.MVCorei18n.CONFIG_NODE_NOTFOUND;
import static com.onarandombox.MultiverseCore.utils.message.MessageReplacement.replace;
public class ConfigNodeNotFoundException extends MultiverseException {
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.configuration.node;
package com.onarandombox.MultiverseCore.configuration.node;
import org.jetbrains.annotations.NotNull;
@@ -1,4 +1,4 @@
package org.mvplugins.multiverse.core.configuration.node;
package com.onarandombox.MultiverseCore.configuration.node;
import java.util.ArrayList;
import java.util.Collection;
@@ -9,7 +9,6 @@ import java.util.Map;
import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode;
import io.vavr.control.Option;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A collection of {@link CommentedNode}s, with mappings to nodes by name.
@@ -18,32 +17,24 @@ public class NodeGroup implements Collection<Node> {
private final Collection<Node> nodes;
private final Map<String, Node> nodesMap;
/**
* Creates a new empty node group.
*/
public NodeGroup() {
this.nodes = new ArrayList<>();
this.nodesMap = new HashMap<>();
}
/**
* Creates a new node group with the given nodes.
*
* @param nodes The nodes to make up the group.
*/
public NodeGroup(@NotNull Collection<Node> nodes) {
public NodeGroup(Collection<Node> nodes) {
this.nodes = nodes;
this.nodesMap = new HashMap<>(nodes.size());
nodes.forEach(this::addNodeIndex);
}
private void addNodeIndex(@NotNull Node node) {
private void addNodeIndex(Node node) {
if (node instanceof ValueNode) {
((ValueNode<?>) node).getName().peek(name -> nodesMap.put(name, node));
}
}
private void removeNodeIndex(@NotNull Node node) {
private void removeNodeIndex(Node node) {
if (node instanceof ValueNode) {
((ValueNode<?>) node).getName().peek(nodesMap::remove);
}
@@ -54,29 +45,28 @@ public class NodeGroup implements Collection<Node> {
*
* @return The names of all nodes in this group.
*/
public @NotNull Collection<String> getNames() {
public Collection<String> getNames() {
return nodesMap.keySet();
}
/**
* Gets the node with the given name.
*
* @param name The name of the node to get.
* @param name The name of the node to get.
* @return The node with the given name, or {@link Option.None} if no node with the given name exists.
*/
public @NotNull Option<Node> findNode(@Nullable String name) {
public Option<Node> findNode(String name) {
return Option.of(nodesMap.get(name));
}
/**
* Gets the node with the given name.
*
* @param name The name of node to get.
* @param type The type of node to get.
* @param <T> The type of node.
* @param name The name of the node to get.
* @param type The type of the node to get.
* @return The node with the given name, or {@link Option.None} if no node with the given name exists.
*/
public <T extends Node> @NotNull Option<T> findNode(@Nullable String name, @NotNull Class<T> type) {
public <T extends Node> Option<T> findNode(String name, Class<T> type) {
return Option.of(nodesMap.get(name)).map(node -> type.isAssignableFrom(node.getClass()) ? (T) node : null);
}
@@ -1,14 +1,10 @@
package org.mvplugins.multiverse.core.configuration.node;
import java.util.Collection;
package com.onarandombox.MultiverseCore.configuration.node;
import io.vavr.control.Option;
import io.vavr.control.Try;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.mvplugins.multiverse.core.configuration.functions.NodeSerializer;
public interface ValueNode<T> extends Node {
/**
@@ -32,35 +28,11 @@ public interface ValueNode<T> extends Node {
*/
@Nullable T getDefaultValue();
/**
* Suggests possible string values for this node. Generated based on the current user input.
*
* @param input The current partial user input
* @return A collection of possible string values.
*/
@NotNull Collection<String> suggest(@Nullable String input);
/**
* Parses the given string into a value of type {@link T}. Used for property set by user input.
*
* @param input The string to parse.
* @return The parsed value, or given exception if parsing failed.
*/
@NotNull Try<T> parseFromString(@Nullable String input);
/**
* Gets the serializer for this node.
*
* @return The serializer for this node.
*/
@Nullable NodeSerializer<T> getSerializer();
/**
* Validates the value of this node.
*
* @param value The value to validate.
* @return An empty {@link Try} if the value is valid, or a {@link Try} containing an exception if the value is
* invalid.
* @return True if the value is valid, false otherwise.
*/
Try<Void> validate(@Nullable T value);
@@ -0,0 +1,213 @@
package com.onarandombox.MultiverseCore.destination;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.CommandIssuer;
import com.onarandombox.MultiverseCore.api.Destination;
import com.onarandombox.MultiverseCore.api.DestinationInstance;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.api.Teleporter;
import com.onarandombox.MultiverseCore.teleportation.TeleportResult;
import jakarta.inject.Inject;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.PluginManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
/**
* Provides destinations for teleportation.
*/
@Service
public class DestinationsProvider {
private static final String SEPARATOR = ":";
private static final String PERMISSION_PREFIX = "multiverse.teleport.";
private final PluginManager pluginManager;
private final SafeTTeleporter safeTTeleporter;
private final Map<String, Destination<?>> destinationMap;
/**
* Creates a new destinations provider.
*/
@Inject
public DestinationsProvider(@NotNull PluginManager pluginManager, @NotNull SafeTTeleporter safeTTeleporter) {
this.pluginManager = pluginManager;
this.safeTTeleporter = safeTTeleporter;
this.destinationMap = new HashMap<>();
}
/**
* Adds a destination to the provider.
*
* @param destination The destination.
*/
public void registerDestination(@NotNull Destination<?> destination) {
this.destinationMap.put(destination.getIdentifier(), destination);
this.registerDestinationPerms(destination);
}
private void registerDestinationPerms(@NotNull Destination<?> destination) {
pluginManager.addPermission(new Permission(PERMISSION_PREFIX + "self." + destination.getIdentifier()));
pluginManager.addPermission(new Permission(PERMISSION_PREFIX + "other." + destination.getIdentifier()));
}
/**
* Suggest tab completions for a destination string.
*
* @param issuer The command issuer.
* @param deststring The current destination string.
* @return A collection of tab completions.
*/
public @NotNull Collection<String> suggestDestinations(@NotNull BukkitCommandIssuer issuer,
@Nullable String deststring
) {
return destinationMap.values().stream()
.filter(destination -> issuer.hasPermission(PERMISSION_PREFIX + "self." + destination.getIdentifier())
|| issuer.hasPermission(PERMISSION_PREFIX + "other." + destination.getIdentifier()))
.map(destination -> destination.suggestDestinations(issuer, deststring).stream()
.map(s -> destination.getIdentifier() + SEPARATOR + s)
.collect(Collectors.toList()))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
/**
* Converts a destination string to a destination object.
*
* @param destinationString The destination string.
* @return The destination object, or null if invalid format.
*/
public ParsedDestination<?> parseDestination(String destinationString) {
String[] items = destinationString.split(SEPARATOR, 2);
String idString = items[0];
String destinationParams;
Destination<?> destination;
if (items.length < 2) {
// Assume world destination
destination = this.getDestinationById("w");
destinationParams = items[0];
} else {
destination = this.getDestinationById(idString);
destinationParams = items[1];
}
if (destination == null) {
return null;
}
DestinationInstance destinationInstance = destination.getDestinationInstance(destinationParams);
if (destinationInstance == null) {
return null;
}
return new ParsedDestination<>(destination, destinationInstance);
}
/**
* Gets a destination by its identifier.
*
* @param identifier The identifier.
* @return The destination, or null if not found.
*/
public @Nullable Destination<?> getDestinationById(@Nullable String identifier) {
return this.destinationMap.get(identifier);
}
/**
* Teleports the teleportee to the destination.
*
* @param teleporter The teleporter.
* @param teleportee The teleportee.
* @param destination The destination.
*/
public CompletableFuture<TeleportResult> playerTeleportAsync(@NotNull BukkitCommandIssuer teleporter,
@NotNull Player teleportee,
@NotNull ParsedDestination<?> destination
) {
if (!checkTeleportPermissions(teleporter, teleportee, destination)) {
return CompletableFuture.completedFuture(TeleportResult.FAIL_PERMISSION);
}
return teleportAsync(teleporter, teleportee, destination);
}
/**
* Teleports the teleportee to the destination.
*
* @param teleporter The teleporter.
* @param teleportee The teleportee.
* @param destination The destination.
*/
public CompletableFuture<TeleportResult> teleportAsync(@NotNull BukkitCommandIssuer teleporter,
@NotNull Entity teleportee,
@NotNull ParsedDestination<?> destination
) {
Teleporter teleportHandler = destination.getDestination().getTeleporter();
if (teleportHandler == null) {
teleportHandler = safeTTeleporter;
}
return teleportHandler.teleportAsync(teleporter, teleportee, destination);
}
/**
* Checks if the teleporter has permission to teleport the teleportee to the destination.
*
* @param teleporter The teleporter.
* @param teleportee The teleportee.
* @param destination The destination.
* @return True if the teleporter has permission, false otherwise.
*/
public boolean checkTeleportPermissions(CommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination) {
//TODO Move permission checking to a separate class
String permission = PERMISSION_PREFIX
+ (teleportee.equals(teleporter.getIssuer()) ? "self" : "other") + "."
+ destination.getDestination().getIdentifier();
if (!teleporter.hasPermission(permission)) {
teleporter.sendMessage("You don't have permission to teleport to this destination.");
return false;
}
//TODO Config whether to use finer permission
String finerPermissionSuffix = destination.getDestinationInstance().getFinerPermissionSuffix();
if (finerPermissionSuffix == null || finerPermissionSuffix.isEmpty()) {
return true;
}
String finerPermission = permission + "." + finerPermissionSuffix;
if (!teleporter.hasPermission(finerPermission)) {
teleporter.sendMessage("You don't have permission to teleport to this destination.");
return false;
}
return true;
}
/**
* Checks if the issuer has permission to teleport to at least one destination.
*
* @param issuer The issuer.
* @return True if the issuer has permission, false otherwise.
*/
public boolean hasAnyTeleportPermission(CommandIssuer issuer) {
for (Destination<?> destination : this.destinationMap.values()) {
String permission = PERMISSION_PREFIX + "self." + destination.getIdentifier();
if (issuer.hasPermission(permission)) {
return true;
}
permission = PERMISSION_PREFIX + "other." + destination.getIdentifier();
if (issuer.hasPermission(permission)) {
return true;
}
}
return false;
}
}
Loaded 100 of 370 files, more files were not shown because too many files have changed in this diff. Show more