Merge remote-tracking branch 'origin/MV5' into revamp-config

This commit is contained in:
Ben Woo 2023-03-22 22:53:50 +08:00
commit f1a9d3a723
No known key found for this signature in database
GPG Key ID: FB2A3645536E12C8
52 changed files with 950 additions and 133 deletions

2
.github/labeler.yml vendored Normal file
View File

@ -0,0 +1,2 @@
prerelease:
- '*'

17
.github/workflows/pr_labeler.yml vendored Normal file
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
.github/workflows/promote_release.yml vendored Normal file
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: '11'
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 }}

View File

@ -28,27 +28,37 @@ jobs:
- name: Create release - name: Create release
id: release id: release
uses: rymndhng/release-on-push-action@v0.27.0 uses: Multiverse/release-on-push-action@support_prerelease
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
bump_version_scheme: norelease bump_version_scheme: norelease
tag_prefix: '' tag_prefix: ''
release_name: "Release <RELEASE_VERSION>" release_name: "<RELEASE_VERSION>"
use_github_release_notes: true 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 - name: Publish package
uses: gradle/gradle-build-action@v2 uses: gradle/gradle-build-action@v2
with: with:
arguments: publish arguments: publish
env: env:
GITHUB_VERSION: ${{ steps.release.outputs.tag_name }} GITHUB_VERSION: ${{ env.VERSION }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload release artifact - name: Upload release artifact
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: build/libs/multiverse-core-${{ steps.release.outputs.tag_name }}.jar file: build/libs/multiverse-core-${{ env.VERSION }}.jar
asset_name: multiverse-core-${{ steps.release.outputs.tag_name }}.jar asset_name: multiverse-core-${{ steps.release.outputs.tag_name }}.jar
tag: ${{ steps.release.outputs.tag_name }} tag: ${{ steps.release.outputs.tag_name }}

View File

@ -15,4 +15,4 @@ jobs:
with: with:
mode: exactly mode: exactly
count: 1 count: 1
labels: "release:major, release:minor, release:patch, no release" labels: "release:major, release:minor, release:patch, no version bump"

View File

@ -26,4 +26,11 @@ jobs:
with: with:
arguments: build arguments: build
env: env:
GITHUB_VERSION: pr${{ github.event.pull_request.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Artifact output
uses: actions/upload-artifact@v3
with:
name: multiverse-core-pr${{ github.event.pull_request.number }}
path: build/libs/multiverse-core-pr${{ github.event.pull_request.number }}.jar

View File

@ -5,16 +5,23 @@ plugins {
id 'maven-publish' id 'maven-publish'
id 'checkstyle' id 'checkstyle'
id 'com.github.johnrengelman.shadow' version '7.1.2' id 'com.github.johnrengelman.shadow' version '7.1.2'
id "org.jetbrains.kotlin.jvm" version "1.8.10"
} }
version = System.getenv('GITHUB_VERSION') ?: 'local' version = System.getenv('GITHUB_VERSION') ?: 'local'
group = 'com.onarandombox.multiversecore' group = 'com.onarandombox.multiversecore'
description = 'Multiverse-Core' description = 'Multiverse-Core'
java.sourceCompatibility = JavaVersion.VERSION_11 java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
repositories { repositories {
mavenLocal() mavenLocal()
mavenCentral()
maven { maven {
url = uri('https://hub.spigotmc.org/nexus/content/repositories/snapshots/') url = uri('https://hub.spigotmc.org/nexus/content/repositories/snapshots/')
} }
@ -48,19 +55,28 @@ repositories {
name = 'glaremasters repo' name = 'glaremasters repo'
url = 'https://repo.glaremasters.me/repository/towny/' url = 'https://repo.glaremasters.me/repository/towny/'
} }
maven {
name = 'PlaceholderAPI'
url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/'
}
}
configurations {
oldTestImplementation.extendsFrom implementation
oldTestRuntime.extendsFrom runtime
} }
dependencies { dependencies {
// Spigot compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
implementation('org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT') {
exclude group: 'junit', module: 'junit'
}
// Economy // Economy
implementation('com.github.MilkBowl:VaultAPI:1.7.1') { implementation('com.github.MilkBowl:VaultAPI:1.7.1') {
exclude group: 'org.bukkit', module: 'bukkit' exclude group: 'org.bukkit', module: 'bukkit'
} }
// PlaceholderAPI
compileOnly 'me.clip:placeholderapi:2.11.2'
// Command Framework // Command Framework
api 'co.aikar:acf-paper:0.5.1-SNAPSHOT' api 'co.aikar:acf-paper:0.5.1-SNAPSHOT'
@ -82,9 +98,21 @@ dependencies {
api 'org.jetbrains:annotations:22.0.0' api 'org.jetbrains:annotations:22.0.0'
// Tests // Tests
testImplementation 'junit:junit:4.13.1' testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10'
testImplementation 'org.mockito:mockito-core:3.11.2' testImplementation 'com.github.seeseemelk:MockBukkit-v1.19:2.141.0'
testImplementation 'commons-io:commons-io:2.7' testImplementation('com.googlecode.json-simple:json-simple:1.1.1') {
exclude group: 'junit', module: 'junit'
}
testImplementation 'org.jetbrains.kotlin:kotlin-test'
// Old Tests
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'
}
oldTestImplementation 'junit:junit:4.13.1'
oldTestImplementation 'org.mockito:mockito-core:3.11.2'
oldTestImplementation 'commons-io:commons-io:2.7'
} }
@ -109,6 +137,19 @@ configurations {
} }
} }
sourceSets {
oldTest {
java {
compileClasspath += main.output
runtimeClasspath += main.output
srcDir file('src/old-test/java')
}
resources.srcDir file('src/old-test/resources')
}
}
publishing { publishing {
publications { publications {
maven(MavenPublication) { maven(MavenPublication) {
@ -143,6 +184,19 @@ compileJava {
source = prepareSource.outputs source = prepareSource.outputs
} }
compileKotlin {
// We're not using Kotlin in the plugin itself, just tests!
enabled = false
}
configurations {
compileOnly {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
}
runtimeOnly {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
}
}
processResources { processResources {
def props = [version: "${project.version}"] def props = [version: "${project.version}"]
inputs.properties props inputs.properties props
@ -184,14 +238,17 @@ shadowJar {
configurations = [project.configurations.api] configurations = [project.configurations.api]
archiveFileName = "$baseName-$version.$extension" archiveFileName = "$baseName-$version.$extension"
dependencies {
exclude(dependency {
it.moduleGroup == 'org.jetbrains.kotlin'
})
}
} }
build.dependsOn shadowJar build.dependsOn shadowJar
jar.enabled = false jar.enabled = false
// Excludes all test
// TODO: Remove this when we have tests for MV5
test { test {
exclude '**/*' useJUnitPlatform()
} }

View File

@ -33,6 +33,7 @@ import com.onarandombox.MultiverseCore.commands.LoadCommand;
import com.onarandombox.MultiverseCore.commands.RegenCommand; import com.onarandombox.MultiverseCore.commands.RegenCommand;
import com.onarandombox.MultiverseCore.commands.ReloadCommand; import com.onarandombox.MultiverseCore.commands.ReloadCommand;
import com.onarandombox.MultiverseCore.commands.RemoveCommand; import com.onarandombox.MultiverseCore.commands.RemoveCommand;
import com.onarandombox.MultiverseCore.commands.RootCommand;
import com.onarandombox.MultiverseCore.commands.TeleportCommand; import com.onarandombox.MultiverseCore.commands.TeleportCommand;
import com.onarandombox.MultiverseCore.commands.UnloadCommand; import com.onarandombox.MultiverseCore.commands.UnloadCommand;
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager; import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
@ -53,6 +54,7 @@ import com.onarandombox.MultiverseCore.listeners.MVPortalListener;
import com.onarandombox.MultiverseCore.listeners.MVWeatherListener; import com.onarandombox.MultiverseCore.listeners.MVWeatherListener;
import com.onarandombox.MultiverseCore.listeners.MVWorldInitListener; import com.onarandombox.MultiverseCore.listeners.MVWorldInitListener;
import com.onarandombox.MultiverseCore.listeners.MVWorldListener; import com.onarandombox.MultiverseCore.listeners.MVWorldListener;
import com.onarandombox.MultiverseCore.placeholders.MultiverseCorePlaceholders;
import com.onarandombox.MultiverseCore.teleportation.SimpleBlockSafety; import com.onarandombox.MultiverseCore.teleportation.SimpleBlockSafety;
import com.onarandombox.MultiverseCore.teleportation.SimpleLocationManipulation; import com.onarandombox.MultiverseCore.teleportation.SimpleLocationManipulation;
import com.onarandombox.MultiverseCore.teleportation.SimpleSafeTTeleporter; import com.onarandombox.MultiverseCore.teleportation.SimpleSafeTTeleporter;
@ -155,8 +157,10 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
this.anchorManager.loadAnchors(); this.anchorManager.loadAnchors();
this.registerEvents(); this.registerEvents();
this.registerCommands(); this.registerCommands();
this.setUpLocales();
this.registerDestinations(); this.registerDestinations();
this.setupMetrics(); this.setupMetrics();
this.setupPlaceholderAPI();
this.saveMVConfig(); this.saveMVConfig();
this.logEnableMessage(); this.logEnableMessage();
} }
@ -202,10 +206,20 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
this.commandManager.registerCommand(new RegenCommand(this)); this.commandManager.registerCommand(new RegenCommand(this));
this.commandManager.registerCommand(new ReloadCommand(this)); this.commandManager.registerCommand(new ReloadCommand(this));
this.commandManager.registerCommand(new RemoveCommand(this)); this.commandManager.registerCommand(new RemoveCommand(this));
this.commandManager.registerCommand(new RootCommand(this));
this.commandManager.registerCommand(new TeleportCommand(this)); this.commandManager.registerCommand(new TeleportCommand(this));
this.commandManager.registerCommand(new UnloadCommand(this)); this.commandManager.registerCommand(new UnloadCommand(this));
} }
/**
* Register locales
*/
private void setUpLocales() {
this.commandManager.usePerIssuerLocale(true, true);
this.commandManager.getLocales().addFileResClassLoader(this);
this.commandManager.getLocales().addMessageBundles("multiverse-core");
}
/** /**
* Register all the destinations. * Register all the destinations.
*/ */
@ -240,6 +254,12 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
} }
} }
private void setupPlaceholderAPI() {
if(getServer().getPluginManager().getPlugin("PlaceholderAPI") != null) {
new MultiverseCorePlaceholders(this).register();
}
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -9,6 +9,7 @@ import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.destination.ParsedDestination; import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -22,18 +23,20 @@ public class CheckCommand extends MultiverseCoreCommand {
@CommandPermission("multiverse.core.check") @CommandPermission("multiverse.core.check")
@CommandCompletion("@players @destinations|@mvworlds") @CommandCompletion("@players @destinations|@mvworlds")
@Syntax("<player> <destination>") @Syntax("<player> <destination>")
@Description("Checks if a player can teleport to a destination.") @Description("{@@mv-core.check.description}")
public void onCheckCommand(BukkitCommandIssuer issuer, public void onCheckCommand(BukkitCommandIssuer issuer,
@Syntax("<player>") @Syntax("<player>")
@Description("Player to check destination on.") @Description("{@@mv-core.check.player.description}")
Player player, Player player,
@Syntax("<destination>") @Syntax("<destination>")
@Description("A destination location, e.g. a world name.") @Description("{@@mv-core.check.destination.description}")
ParsedDestination<?> destination ParsedDestination<?> destination
) { ) {
issuer.sendMessage("Checking " + player + " to " + destination + "..."); issuer.sendInfo(MVCorei18n.CHECK_CHECKING,
"{player}", player.getName(),
"{destination}", destination.toString());
//TODO More detailed output on permissions required. //TODO More detailed output on permissions required.
this.plugin.getDestinationsProvider().checkTeleportPermissions(issuer, player, destination); this.plugin.getDestinationsProvider().checkTeleportPermissions(issuer, player, destination);
} }

View File

@ -10,6 +10,7 @@ import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -23,26 +24,29 @@ public class CloneCommand extends MultiverseCoreCommand {
@CommandPermission("multiverse.core.clone") @CommandPermission("multiverse.core.clone")
@CommandCompletion("@mvworlds:scope=both @empty") @CommandCompletion("@mvworlds:scope=both @empty")
@Syntax("<world> <new world name>") @Syntax("<world> <new world name>")
@Description("Clones a world.") @Description("{@@mv-core.clone.description}")
public void onCloneCommand(CommandIssuer issuer, public void onCloneCommand(CommandIssuer issuer,
@Conditions("validWorldName:scope=both") @Conditions("validWorldName:scope=both")
@Syntax("<world>") @Syntax("<world>")
@Description("The target world to clone.") @Description("{@@mv-core.clone.world.description}")
String worldName, String worldName,
@Single @Single
@Conditions("validWorldName:scope=new") @Conditions("validWorldName:scope=new")
@Syntax("<new world name>") @Syntax("<new world name>")
@Description("The new cloned world name.") @Description("{@@mv-core.clone.newWorld.description}")
String newWorldName String newWorldName
) { ) {
issuer.sendMessage(String.format("Cloning world '%s' to '%s'...", worldName, newWorldName)); issuer.sendInfo(MVCorei18n.CLONE_CLONING,
"{world}", worldName,
"{newWorld}", newWorldName);
if (!this.plugin.getMVWorldManager().cloneWorld(worldName, newWorldName)) { if (!this.plugin.getMVWorldManager().cloneWorld(worldName, newWorldName)) {
issuer.sendMessage(String.format("%sWorld could not be cloned! See console for more details.", ChatColor.RED)); issuer.sendError(MVCorei18n.CLONE_FAILED);
return; return;
} }
issuer.sendMessage(String.format("%sCloned world '%s'!", ChatColor.GREEN, newWorldName)); issuer.sendInfo(MVCorei18n.CLONE_SUCCESS,
"{world}", newWorldName);
} }
} }

View File

@ -16,7 +16,7 @@ public class ConfirmCommand extends MultiverseCoreCommand {
@Subcommand("confirm") @Subcommand("confirm")
@CommandPermission("multiverse.core.confirm") @CommandPermission("multiverse.core.confirm")
@Description("Confirms dangerous commands before executing them.") @Description("{@@mv-core.confirm.description}")
public void onConfirmCommand(@NotNull BukkitCommandIssuer issuer) { public void onConfirmCommand(@NotNull BukkitCommandIssuer issuer) {
this.plugin.getMVCommandManager().getCommandQueueManager().runQueuedCommand(issuer.getIssuer()); this.plugin.getMVCommandManager().getCommandQueueManager().runQueuedCommand(issuer.getIssuer());
} }

View File

@ -22,7 +22,7 @@ import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup; import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag; import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags; import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import com.onarandombox.MultiverseCore.locale.MVCorei18n; import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.WorldType; import org.bukkit.WorldType;

View File

@ -9,7 +9,7 @@ import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Syntax;
import com.dumptruckman.minecraft.util.Logging; import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.locale.MVCorei18n; import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@CommandAlias("mv") @CommandAlias("mv")

View File

@ -1,6 +1,7 @@
package com.onarandombox.MultiverseCore.commands; package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.BukkitCommandIssuer; import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.MessageType;
import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion; import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission; import co.aikar.commands.annotation.CommandPermission;
@ -10,7 +11,9 @@ import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVCore;
import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand; import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -24,7 +27,7 @@ public class DeleteCommand extends MultiverseCoreCommand {
@CommandPermission("multiverse.core.delete") @CommandPermission("multiverse.core.delete")
@CommandCompletion("@mvworlds:scope=both") @CommandCompletion("@mvworlds:scope=both")
@Syntax("<world>") @Syntax("<world>")
@Description("Deletes a world on your server PERMANENTLY.") @Description("{@@mv-core.delete.description}")
public void onDeleteCommand(BukkitCommandIssuer issuer, public void onDeleteCommand(BukkitCommandIssuer issuer,
@Single @Single
@ -36,14 +39,21 @@ public class DeleteCommand extends MultiverseCoreCommand {
this.plugin.getMVCommandManager().getCommandQueueManager().addToQueue(new QueuedCommand( this.plugin.getMVCommandManager().getCommandQueueManager().addToQueue(new QueuedCommand(
issuer.getIssuer(), issuer.getIssuer(),
() -> { () -> {
issuer.sendMessage(String.format("Deleting world '%s'...", worldName)); issuer.sendInfo(MVCorei18n.DELETE_DELETING,
"{world}", worldName);
if (!this.plugin.getMVWorldManager().deleteWorld(worldName)) { if (!this.plugin.getMVWorldManager().deleteWorld(worldName)) {
issuer.sendMessage(String.format("%sThere was an issue deleting '%s'! Please check console for errors.", ChatColor.RED, worldName)); issuer.sendError(MVCorei18n.DELETE_FAILED,
"{world}", worldName);
return; return;
} }
issuer.sendMessage(String.format("%sWorld %s was deleted!", ChatColor.GREEN, worldName)); issuer.sendInfo(MVCorei18n.DELETE_SUCCESS,
"{world}", worldName);
}, },
"Are you sure you want to delete world '" + worldName + "'?" this.plugin.getMVCommandManager().formatMessage(
issuer,
MessageType.INFO,
MVCorei18n.DELETE_PROMPT,
"{world}", worldName)
)); ));
} }
} }

View File

@ -11,6 +11,7 @@ import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorld; import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.commandtools.context.GameRuleValue; import com.onarandombox.MultiverseCore.commandtools.context.GameRuleValue;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.GameRule; import org.bukkit.GameRule;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -25,20 +26,20 @@ public class GameruleCommand extends MultiverseCoreCommand {
@CommandPermission("multiverse.core.gamerule") @CommandPermission("multiverse.core.gamerule")
@CommandCompletion("@gamerules true|false|@range:1-10 @mvworlds:multiple|*") @CommandCompletion("@gamerules true|false|@range:1-10 @mvworlds:multiple|*")
@Syntax("<Gamerule> <Gamerule value> [World or *]") @Syntax("<Gamerule> <Gamerule value> [World or *]")
@Description("Changes a gamerule in one or more worlds") @Description("{@@mv-core.gamerule.description}")
public void onGameruleCommand(BukkitCommandIssuer issuer, public void onGameruleCommand(BukkitCommandIssuer issuer,
@Syntax("<Gamerule>") @Syntax("<Gamerule>")
@Description("Gamerule to set") @Description("{@@mv-core.gamerule.gamerule.description}")
GameRule gamerule, GameRule gamerule,
@Syntax("<Value>") @Syntax("<Value>")
@Description("Value of gamerule") @Description("{@@mv-core.gamerule.value.description}")
GameRuleValue gameRuleValue, GameRuleValue gameRuleValue,
@Flags("resolve=issuerAware") @Flags("resolve=issuerAware")
@Syntax("[World or *]") @Syntax("[World or *]")
@Description("World to apply gamerule to, current world by default") @Description("{@@mv-core.gamerule.world.description}")
MVWorld[] worlds MVWorld[] worlds
) { ) {
Object value = gameRuleValue.getValue(); Object value = gameRuleValue.getValue();
@ -46,17 +47,27 @@ public class GameruleCommand extends MultiverseCoreCommand {
for(MVWorld world : worlds) { for(MVWorld world : worlds) {
// Set gamerules and add false to list if it fails // Set gamerules and add false to list if it fails
if (!world.getCBWorld().setGameRule(gamerule, value)) { if (!world.getCBWorld().setGameRule(gamerule, value)) {
issuer.sendMessage(ChatColor.RED + "Failed to set gamerule " + gamerule.getName() + " to " + value + " in " + world.getName() + ". It should be a " + gamerule.getType()); issuer.sendError(MVCorei18n.GAMERULE_FAILED,
"{gamerule}", gamerule.getName(),
"{value}", value.toString(),
"{world}", world.getName(),
"{type}", gamerule.getType().getName());
success = false; success = false;
} }
} }
// Tell user if it was successful // Tell user if it was successful
if (success) { if (success) {
if (worlds.length == 1) { if (worlds.length == 1) {
issuer.sendMessage(ChatColor.GREEN + "Successfully set " + gamerule.getName() + " to " + value + " in " + worlds[0].getName()); issuer.sendInfo(MVCorei18n.GAMERULE_SUCCESS_SINGLE,
"{gamerule}", gamerule.getName(),
"{value}", value.toString(),
"{world}", worlds[0].getName());
} }
else if (worlds.length > 1) { else if (worlds.length > 1) {
issuer.sendMessage(ChatColor.GREEN + "Successfully set " + gamerule.getName() + " to " + value + " in " + worlds.length + " worlds."); issuer.sendInfo(MVCorei18n.GAMERULE_SUCCESS_MULTIPLE,
"{gamerule}", gamerule.getName(),
"{value}", value.toString(),
"{count}", String.valueOf(worlds.length));
} }
} }
} }

View File

@ -13,10 +13,12 @@ import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVCore;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag; import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup; import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag; import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags; import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.World; import org.bukkit.World;
@ -51,26 +53,27 @@ public class ImportCommand extends MultiverseCoreCommand {
@CommandPermission("multiverse.core.import") @CommandPermission("multiverse.core.import")
@CommandCompletion("@mvworlds:scope=potential @flags:groupName=mvimport") @CommandCompletion("@mvworlds:scope=potential @flags:groupName=mvimport")
@Syntax("<name> <env> --generator [generator[:id]] --adjust-spawn") @Syntax("<name> <env> --generator [generator[:id]] --adjust-spawn")
@Description("Imports a existing world folder.") @Description("{@@mv-core.import.description")
public void onImportCommand(BukkitCommandIssuer issuer, public void onImportCommand(BukkitCommandIssuer issuer,
@Conditions("validWorldName:scope=new") @Conditions("validWorldName:scope=new")
@Syntax("<name>") @Syntax("<name>")
@Description("Name of the world folder.") @Description("{@@mv-core.import.name.description}")
String worldName, String worldName,
@Syntax("<env>") @Syntax("<env>")
@Description("The world's environment. See: /mv env") @Description("{@@mv-core.import.env.description}")
World.Environment environment, World.Environment environment,
@Optional @Optional
@Syntax("--generator [generator[:id]] --adjust-spawn") @Syntax("--generator [generator[:id]] --adjust-spawn")
@Description("Other world settings. See: https://gg.gg/nn8c2") @Description("{@@mv-core.import.other.description}")
String[] flags) { String[] flags) {
ParsedCommandFlags parsedFlags = parseFlags(flags); ParsedCommandFlags parsedFlags = parseFlags(flags);
issuer.sendMessage(String.format("Starting import of world '%s'...", worldName)); issuer.sendInfo(MVCorei18n.IMPORT_IMPORTING,
"{world}", worldName);
if (!this.worldManager.addWorld( if (!this.worldManager.addWorld(
worldName, environment, worldName, environment,
@ -80,9 +83,9 @@ public class ImportCommand extends MultiverseCoreCommand {
parsedFlags.flagValue("--generator", String.class), parsedFlags.flagValue("--generator", String.class),
parsedFlags.hasFlag("--adjust-spawn")) parsedFlags.hasFlag("--adjust-spawn"))
) { ) {
issuer.sendMessage(String.format("%sFailed! See console for more details.", ChatColor.RED)); issuer.sendError(MVCorei18n.IMPORT_FAILED);
return; return;
} }
issuer.sendMessage(String.format("%sComplete!", ChatColor.GREEN)); issuer.sendInfo(MVCorei18n.IMPORT_SUCCESS);
} }
} }

View File

@ -10,6 +10,7 @@ import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@CommandAlias("mv") @CommandAlias("mv")
@ -22,21 +23,24 @@ public class LoadCommand extends MultiverseCoreCommand {
@CommandPermission("multiverse.core.load") @CommandPermission("multiverse.core.load")
@CommandCompletion("@mvworlds:scope=unloaded") @CommandCompletion("@mvworlds:scope=unloaded")
@Syntax("<world>") @Syntax("<world>")
@Description("Loads a world. World must be already in worlds.yml, else please use /mv import.") @Description("{@@mv-core.load.description}")
public void onLoadCommand(BukkitCommandIssuer issuer, public void onLoadCommand(BukkitCommandIssuer issuer,
@Single @Single
@Conditions("validWorldName:scope=unloaded") @Conditions("validWorldName:scope=unloaded")
@Syntax("<world>") @Syntax("<world>")
@Description("Name of world you want to load.") @Description("{@@mv-core.load.world.description}")
String worldName String worldName
) { ) {
issuer.sendMessage(String.format("Loading world '%s'...", worldName)); issuer.sendInfo(MVCorei18n.LOAD_LOADING,
"{world}", worldName);
if (!this.plugin.getMVWorldManager().loadWorld(worldName)) { if (!this.plugin.getMVWorldManager().loadWorld(worldName)) {
issuer.sendMessage(String.format("Error trying to load world '%s'!", worldName)); issuer.sendError(MVCorei18n.LOAD_FAILED,
"{world}", worldName);
return; return;
} }
issuer.sendMessage(String.format("Loaded world '%s'!", worldName)); issuer.sendInfo(MVCorei18n.LOAD_SUCCESS,
"{world}", worldName);
} }
} }

View File

@ -4,6 +4,7 @@ import java.util.Collections;
import java.util.Random; import java.util.Random;
import co.aikar.commands.BukkitCommandIssuer; import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.MessageType;
import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion; import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission; import co.aikar.commands.annotation.CommandPermission;
@ -18,6 +19,7 @@ import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagGroup;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag; import com.onarandombox.MultiverseCore.commandtools.flags.CommandValueFlag;
import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags; import com.onarandombox.MultiverseCore.commandtools.flags.ParsedCommandFlags;
import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand; import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -42,17 +44,17 @@ public class RegenCommand extends MultiverseCoreCommand {
@CommandPermission("multiverse.core.regen") @CommandPermission("multiverse.core.regen")
@CommandCompletion("@mvworlds:scope=both @flags:groupName=mvregen") @CommandCompletion("@mvworlds:scope=both @flags:groupName=mvregen")
@Syntax("<world> --seed [seed] --keep-gamerules") @Syntax("<world> --seed [seed] --keep-gamerules")
@Description("Regenerates a world on your server. The previous state will be lost PERMANENTLY.") @Description("{@@mv-core.regen.description}")
public void onRegenCommand(BukkitCommandIssuer issuer, public void onRegenCommand(BukkitCommandIssuer issuer,
@Conditions("validWorldName:scope=both") @Conditions("validWorldName:scope=both")
@Syntax("<world>") @Syntax("<world>")
@Description("World that you want to regen.") @Description("{@@mv-core.regen.world.description}")
String worldName, String worldName,
@Optional @Optional
@Syntax("--seed [seed] --keep-gamerules") @Syntax("--seed [seed] --keep-gamerules")
@Description("Other world settings. See: http://gg.gg/nn8lk") @Description("{@@mv-core.regen.other.description}")
String[] flags String[] flags
) { ) {
ParsedCommandFlags parsedFlags = parseFlags(flags); ParsedCommandFlags parsedFlags = parseFlags(flags);
@ -60,7 +62,8 @@ public class RegenCommand extends MultiverseCoreCommand {
this.plugin.getMVCommandManager().getCommandQueueManager().addToQueue(new QueuedCommand( this.plugin.getMVCommandManager().getCommandQueueManager().addToQueue(new QueuedCommand(
issuer.getIssuer(), issuer.getIssuer(),
() -> { () -> {
issuer.sendMessage(String.format("Regenerating world '%s'...", worldName)); issuer.sendInfo(MVCorei18n.REGEN_REGENERATING,
"{world}", worldName);
if (!this.plugin.getMVWorldManager().regenWorld( if (!this.plugin.getMVWorldManager().regenWorld(
worldName, worldName,
parsedFlags.hasFlag("--seed"), parsedFlags.hasFlag("--seed"),
@ -68,12 +71,18 @@ public class RegenCommand extends MultiverseCoreCommand {
parsedFlags.flagValue("--seed", String.class), parsedFlags.flagValue("--seed", String.class),
parsedFlags.hasFlag("--keep-gamerules") parsedFlags.hasFlag("--keep-gamerules")
)) { )) {
issuer.sendMessage(String.format("%sThere was an issue regenerating '%s'! Please check console for errors.", ChatColor.RED, worldName)); issuer.sendError(MVCorei18n.REGEN_FAILED,
"{world}", worldName);
return; return;
} }
issuer.sendMessage(String.format("%sWorld %s was regenerated!", ChatColor.GREEN, worldName)); issuer.sendInfo(MVCorei18n.REGEN_SUCCESS,
"{world}", worldName);
}, },
"Are you sure you want to regenerate world '" + worldName + "'?" this.plugin.getMVCommandManager().formatMessage(
issuer,
MessageType.INFO,
MVCorei18n.REGEN_PROMPT,
"{world}", worldName)
)); ));
} }
} }

View File

@ -10,6 +10,7 @@ import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Subcommand;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.event.MVConfigReloadEvent; import com.onarandombox.MultiverseCore.event.MVConfigReloadEvent;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -21,9 +22,9 @@ public class ReloadCommand extends MultiverseCoreCommand {
@Subcommand("reload") @Subcommand("reload")
@CommandPermission("multiverse.core.reload") @CommandPermission("multiverse.core.reload")
@Description("Reloads config files for all multiverse modules.") @Description("{@@mv-core.reload.description}")
public void onReloadCommand(@NotNull BukkitCommandIssuer issuer) { public void onReloadCommand(@NotNull BukkitCommandIssuer issuer) {
issuer.sendMessage(ChatColor.GOLD + "Reloading all Multiverse Plugin configs..."); issuer.sendInfo(MVCorei18n.RELOAD_RELOADING);
this.plugin.loadConfigs(); this.plugin.loadConfigs();
this.plugin.getAnchorManager().loadAnchors(); this.plugin.getAnchorManager().loadAnchors();
this.plugin.getMVWorldManager().loadWorlds(true); this.plugin.getMVWorldManager().loadWorlds(true);
@ -36,7 +37,8 @@ public class ReloadCommand extends MultiverseCoreCommand {
MVConfigReloadEvent configReload = new MVConfigReloadEvent(configsLoaded); MVConfigReloadEvent configReload = new MVConfigReloadEvent(configsLoaded);
this.plugin.getServer().getPluginManager().callEvent(configReload); this.plugin.getServer().getPluginManager().callEvent(configReload);
// @TODO: replace this sendMessage and format the configsLoaded above, maybe?
configReload.getAllConfigsLoaded().forEach(issuer::sendMessage); configReload.getAllConfigsLoaded().forEach(issuer::sendMessage);
issuer.sendMessage(String.format("%sReload Complete!", ChatColor.GREEN)); issuer.sendInfo(MVCorei18n.RELOAD_SUCCESS);
} }
} }

View File

@ -10,6 +10,7 @@ import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -23,19 +24,20 @@ public class RemoveCommand extends MultiverseCoreCommand {
@CommandPermission("multiverse.core.remove") @CommandPermission("multiverse.core.remove")
@CommandCompletion("@mvworlds:scope=both") @CommandCompletion("@mvworlds:scope=both")
@Syntax("<world>") @Syntax("<world>")
@Description("Unloads a world from Multiverse and removes it from worlds.yml, this does NOT DELETE the world folder.") @Description("{@@mv-core.remove.description}")
public void onRemoveCommand(BukkitCommandIssuer issuer, public void onRemoveCommand(BukkitCommandIssuer issuer,
@Single @Single
@Conditions("mvworlds:scope=both") @Conditions("mvworlds:scope=both")
@Syntax("<world>") @Syntax("<world>")
@Description("World you want to remove from mv's knowledge.") @Description("{@@mv-core.remove.world.description}")
String worldName String worldName
) { ) {
if (!this.plugin.getMVWorldManager().removeWorldFromConfig(worldName)) { if (!this.plugin.getMVWorldManager().removeWorldFromConfig(worldName)) {
issuer.sendMessage(String.format("%sError trying to remove world from config!", ChatColor.RED)); issuer.sendError(MVCorei18n.REMOVE_FAILED);
return; return;
} }
issuer.sendMessage(String.format("World '%s' is removed from config!", worldName)); issuer.sendInfo(MVCorei18n.REMOVE_SUCCESS,
"{world}", worldName);
} }
} }

View File

@ -0,0 +1,24 @@
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.utils.MVCorei18n;
import org.bukkit.ChatColor;
import org.bukkit.plugin.PluginDescriptionFile;
import org.jetbrains.annotations.NotNull;
public class RootCommand extends MultiverseCoreCommand {
public RootCommand(@NotNull MultiverseCore plugin) {
super(plugin);
}
@CommandAlias("mv")
public void onRootCommand(CommandIssuer issuer) {
PluginDescriptionFile description = this.plugin.getDescription();
issuer.sendInfo(MVCorei18n.ROOT_TITLE,
"{name}", description.getName(),
"{version}", description.getVersion());
issuer.sendInfo(MVCorei18n.ROOT_HELP);
}
}

View File

@ -10,6 +10,7 @@ import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.destination.ParsedDestination; import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@CommandAlias("mv") @CommandAlias("mv")
@ -21,23 +22,23 @@ public class TeleportCommand extends MultiverseCoreCommand {
@Subcommand("teleport|tp") @Subcommand("teleport|tp")
@CommandCompletion("@players|@mvworlds:playerOnly|@destinations:playerOnly @mvworlds|@destinations") @CommandCompletion("@players|@mvworlds:playerOnly|@destinations:playerOnly @mvworlds|@destinations")
@Syntax("[player] <destination>") @Syntax("[player] <destination>")
@Description("Allows you to the teleport to a location on your server!") @Description("{@@mv-core.teleport.description}")
public void onTeleportCommand(BukkitCommandIssuer issuer, public void onTeleportCommand(BukkitCommandIssuer issuer,
@Flags("resolve=issuerAware") @Flags("resolve=issuerAware")
@Syntax("[player]") @Syntax("[player]")
@Description("Target player to teleport.") @Description("{@@mv-core.teleport.player.description}")
Player[] players, Player[] players,
@Syntax("<destination>") @Syntax("<destination>")
@Description("Location, can be a world name.") @Description("{@@mv-core.teleport.destination.description}")
ParsedDestination<?> destination ParsedDestination<?> destination
) { ) {
// TODO Add warning if teleporting too many players at once. // TODO Add warning if teleporting too many players at once.
for (Player player : players) { for (Player player : players) {
issuer.sendMessage("Teleporting " issuer.sendInfo(MVCorei18n.TELEPORT_SUCCESS,
+ (issuer.getPlayer() == player ? "you" : player.getName()) "{player}", issuer.getPlayer() == player ? "you" : player.getName(),
+ " to " + destination + "..."); "{destination}", destination.toString());
this.plugin.getDestinationsProvider().playerTeleport(issuer, player, destination); this.plugin.getDestinationsProvider().playerTeleport(issuer, player, destination);
} }
} }

View File

@ -9,6 +9,7 @@ import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorld; import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@CommandAlias("mv") @CommandAlias("mv")
@ -21,20 +22,23 @@ public class UnloadCommand extends MultiverseCoreCommand {
@CommandPermission("multiverse.core.unload") @CommandPermission("multiverse.core.unload")
@CommandCompletion("@mvworlds") @CommandCompletion("@mvworlds")
@Syntax("<world>") @Syntax("<world>")
@Description("Unloads a world from Multiverse. This does NOT remove the world folder. This does NOT remove it from the config file.") @Description("{@@mv-core.unload.description}")
public void onUnloadCommand(BukkitCommandIssuer issuer, public void onUnloadCommand(BukkitCommandIssuer issuer,
@Syntax("<world>") @Syntax("<world>")
@Description("Name of the world you want to unload.") @Description("{@@mv-core.unload.world.description}")
MVWorld world MVWorld world
) { ) {
issuer.sendMessage(String.format("Unloading world '%s'...", world.getColoredWorldString())); issuer.sendInfo(MVCorei18n.UNLOAD_UNLOADING,
"{world}", world.getColoredWorldString());
//TODO API: Should be able to use MVWorld object directly //TODO API: Should be able to use MVWorld object directly
if (!this.plugin.getMVWorldManager().unloadWorld(world.getName())) { if (!this.plugin.getMVWorldManager().unloadWorld(world.getName())) {
issuer.sendMessage(String.format("Error unloading world '%s'! See console for more details.", world.getColoredWorldString())); issuer.sendError(MVCorei18n.UNLOAD_FAILURE,
"{world}", world.getColoredWorldString());
return; return;
} }
issuer.sendMessage(String.format("Unloaded world '%s'!", world.getColoredWorldString())); issuer.sendInfo(MVCorei18n.UNLOAD_SUCCESS,
"{world}", world.getColoredWorldString());
} }
} }

View File

@ -0,0 +1,33 @@
package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.CommandHelp;
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.HelpCommand;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.onarandombox.MultiverseCore.MultiverseCore;
import org.jetbrains.annotations.NotNull;
@CommandAlias("mv")
public class UsageCommand extends MultiverseCoreCommand {
public UsageCommand(@NotNull MultiverseCore plugin) {
super(plugin);
}
@HelpCommand
@Subcommand("help")
@CommandPermission("multiverse.core.help")
@CommandCompletion("@commands:mv")
@Syntax("[filter] [page]")
@Description("{@@mv-core.usage.description}")
public void onUsageCommand(CommandHelp help) {
if (help.getIssuer().isPlayer()) {
// Prevent flooding the chat
help.setPerPage(4);
}
this.plugin.getMVCommandManager().showUsage(help);
}
}

View File

@ -5,12 +5,16 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandCompletionContext; import co.aikar.commands.BukkitCommandCompletionContext;
import co.aikar.commands.BukkitCommandIssuer; import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.CommandIssuer;
import co.aikar.commands.PaperCommandCompletions; import co.aikar.commands.PaperCommandCompletions;
import co.aikar.commands.RegisteredCommand;
import co.aikar.commands.RootCommand;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorld; import com.onarandombox.MultiverseCore.api.MVWorld;
@ -30,6 +34,7 @@ public class MVCommandCompletions extends PaperCommandCompletions {
this.plugin = plugin; this.plugin = plugin;
this.worldManager = plugin.getMVWorldManager(); this.worldManager = plugin.getMVWorldManager();
registerAsyncCompletion("commands", this::suggestCommands);
registerAsyncCompletion("destinations", this::suggestDestinations); registerAsyncCompletion("destinations", this::suggestDestinations);
registerAsyncCompletion("flags", this::suggestFlags); registerAsyncCompletion("flags", this::suggestFlags);
registerStaticCompletion("gamerules", this::suggestGamerules); registerStaticCompletion("gamerules", this::suggestGamerules);
@ -41,6 +46,33 @@ public class MVCommandCompletions extends PaperCommandCompletions {
setDefaultCompletion("mvworlds", MVWorld.class); setDefaultCompletion("mvworlds", MVWorld.class);
} }
private Collection<String> suggestCommands(BukkitCommandCompletionContext context) {
String rootCmdName = context.getConfig();
if (rootCmdName == null) {
return Collections.emptyList();
}
RootCommand rootCommand = this.plugin.getMVCommandManager().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.plugin.getMVCommandManager().hasPermission(issuer, command.getRequiredPermissions());
}
private Collection<String> suggestDestinations(BukkitCommandCompletionContext context) { private Collection<String> suggestDestinations(BukkitCommandCompletionContext context) {
if (context.hasConfig("playerOnly") && !context.getIssuer().isPlayer()) { if (context.hasConfig("playerOnly") && !context.getIssuer().isPlayer()) {
return Collections.emptyList(); return Collections.emptyList();

View File

@ -1,11 +1,13 @@
package com.onarandombox.MultiverseCore.commandtools; package com.onarandombox.MultiverseCore.commandtools;
import java.util.Locale; import java.util.List;
import co.aikar.commands.BukkitCommandCompletionContext; import co.aikar.commands.BukkitCommandCompletionContext;
import co.aikar.commands.BukkitCommandExecutionContext; import co.aikar.commands.BukkitCommandExecutionContext;
import co.aikar.commands.CommandCompletions; import co.aikar.commands.CommandCompletions;
import co.aikar.commands.CommandContexts; import co.aikar.commands.CommandContexts;
import co.aikar.commands.CommandHelp;
import co.aikar.commands.HelpEntry;
import co.aikar.commands.PaperCommandManager; import co.aikar.commands.PaperCommandManager;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagsManager; import com.onarandombox.MultiverseCore.commandtools.flags.CommandFlagsManager;
@ -20,6 +22,7 @@ public class MVCommandManager extends PaperCommandManager {
private final MultiverseCore plugin; private final MultiverseCore plugin;
private CommandFlagsManager flagsManager; private CommandFlagsManager flagsManager;
private CommandQueueManager commandQueueManager; private CommandQueueManager commandQueueManager;
private PluginLocales pluginLocales;
public MVCommandManager(@NotNull MultiverseCore plugin) { public MVCommandManager(@NotNull MultiverseCore plugin) {
super(plugin); super(plugin);
@ -27,11 +30,6 @@ public class MVCommandManager extends PaperCommandManager {
// Setup conditions // Setup conditions
MVCommandConditions.load(this, plugin); MVCommandConditions.load(this, plugin);
// Setup locale
this.addSupportedLanguage(Locale.ENGLISH);
this.locales.addMessageBundles("multiverse-core");
this.locales.loadLanguages();
} }
/** /**
@ -46,6 +44,21 @@ public class MVCommandManager extends PaperCommandManager {
return flagsManager; return flagsManager;
} }
/**
* Gets class responsible for locale handling.
*
* @return A not-null {@link PluginLocales}.
*/
@Override
public PluginLocales getLocales() {
if (this.pluginLocales == null) {
this.pluginLocales = new PluginLocales(this);
this.locales = pluginLocales; // For parent class
this.pluginLocales.loadLanguages();
}
return this.pluginLocales;
}
/** /**
* Manager for command that requires /mv confirm before execution. * Manager for command that requires /mv confirm before execution.
* *
@ -83,4 +96,18 @@ public class MVCommandManager extends PaperCommandManager {
} }
return this.completions; return this.completions;
} }
/**
* Standardise usage command formatting for all mv modules.
*
* @param help The target {@link CommandHelp}.
*/
public void showUsage(@NotNull CommandHelp help) {
List<HelpEntry> entries = help.getHelpEntries();
if (entries.size() == 1) {
this.plugin.getMVCommandManager().getHelpFormatter().showDetailedHelp(help, entries.get(0));
return;
}
help.showHelp();
}
} }

View File

@ -0,0 +1,45 @@
package com.onarandombox.MultiverseCore.commandtools;
import co.aikar.commands.BukkitCommandManager;
import co.aikar.commands.BukkitLocales;
import com.onarandombox.MultiverseCore.utils.file.FileResClassLoader;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
/**
* Locale manager with additional methods for loading locales from plugin's locales folder.
*/
public class PluginLocales extends BukkitLocales {
private static final String DEFAULT_LOCALE_FOLDER_PATH = "locales";
/**
* Creates a new instance of {@link PluginLocales}.
*
* @param manager The command manager.
*/
public PluginLocales(BukkitCommandManager manager) {
super(manager);
}
/**
* Adds a {@link FileResClassLoader} to the list of class loaders to load locales data from.
*
* @param plugin The plugin.
* @return True if the class loader was added successfully.
*/
public boolean addFileResClassLoader(@NotNull Plugin plugin) {
return this.addBundleClassLoader(new FileResClassLoader(plugin, DEFAULT_LOCALE_FOLDER_PATH));
}
/**
* Adds a {@link FileResClassLoader} to the list of class loaders to load locales data from.
*
* @param plugin The plugin.
* @param localesFolderPath The path to the folder containing the locales.
* @return True if the class loader was added successfully.
*/
public boolean addFileResClassLoader(@NotNull Plugin plugin, @NotNull String localesFolderPath) {
return this.addBundleClassLoader(new FileResClassLoader(plugin, localesFolderPath));
}
}

View File

@ -1,29 +0,0 @@
package com.onarandombox.MultiverseCore.locale;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
public enum MVCorei18n implements MessageKeyProvider {
CONFIG_SAVE_FAILED,
CREATE_PROPERTIES,
CREATE_PROPERTIES_ENVIRONMENT,
CREATE_PROPERTIES_SEED,
CREATE_PROPERTIES_WORLDTYPE,
CREATE_PROPERTIES_ADJUSTSPAWN,
CREATE_PROPERTIES_GENERATOR,
CREATE_PROPERTIES_STRUCTURES,
CREATE_LOADING,
CREATE_FAILED,
CREATE_SUCCESS,
DEBUG_INFO_OFF,
DEBUG_INFO_ON;
private final MessageKey key = MessageKey.of("mv-core." + this.name().replace('_', '.').toLowerCase());
@Override
public MessageKey getMessageKey() {
return this.key;
}
}

View File

@ -1,4 +0,0 @@
/**
* This package contains all the locale reference for Multiverse-Core.
*/
package com.onarandombox.MultiverseCore.locale;

View File

@ -0,0 +1,155 @@
package com.onarandombox.MultiverseCore.placeholders;
import java.util.Optional;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.economy.MVEconomist;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class MultiverseCorePlaceholders extends PlaceholderExpansion {
private final MultiverseCore plugin;
private final MVWorldManager worldManager;
private final MVEconomist economist;
public MultiverseCorePlaceholders(MultiverseCore plugin) {
this.plugin = plugin;
this.worldManager = plugin.getMVWorldManager();
this.economist = plugin.getEconomist();
}
@Override
public @NotNull String getIdentifier() {
return "multiverse-core";
}
@Override
public @NotNull String getAuthor() {
return plugin.getAuthors();
}
@Override
public @NotNull String getVersion() {
return plugin.getDescription().getVersion();
}
@Override
public boolean persist() {
return true;
}
/**
* Placeholder implementation, format: %multiverse-core_&lt;placeholder&gt;_[world]% world is optional.
*
* @param offlinePlayer Player to get the placeholder for
* @param params Placeholder to get
* @return Placeholder value
*/
@Override
public @Nullable String onRequest(OfflinePlayer offlinePlayer, @NotNull String params) {
// Split string in to an Array with underscores
String[] paramsArray = params.split("_", 2);
// No placeholder defined
if (paramsArray.length < 1) {
warning("No placeholder defined");
return null;
}
final var placeholder = paramsArray[0];
Optional<MVWorld> targetWorld;
// If no world is defined, use the player's world
if (paramsArray.length == 1) {
if (!offlinePlayer.isOnline()) {
return null;
}
targetWorld = Optional.ofNullable(worldManager.getMVWorld(((Player)offlinePlayer).getWorld()));
} else {
targetWorld = Optional.ofNullable(worldManager.getMVWorld(paramsArray[1]));
}
// Fail if world is null
return targetWorld.map(world -> getWorldPlaceHolderValue(placeholder, world))
.orElse(null);
}
private @Nullable String getWorldPlaceHolderValue(@NotNull String placeholder, @NotNull MVWorld world) {
// Switch to find what specific placeholder we want
switch (placeholder.toLowerCase()) {
case "alias" -> {
return world.getColoredWorldString();
}
case "animalspawn" -> {
return String.valueOf(world.canAnimalsSpawn());
}
case "autoheal" -> {
return String.valueOf(world.getAutoHeal());
}
case "blacklist" -> {
return String.join(", ", world.getWorldBlacklist());
}
case "currency" -> {
return String.valueOf(world.getCurrency());
}
case "difficulty" -> {
return world.getDifficulty().toString();
}
case "entryfee" -> {
return economist.formatPrice(world.getPrice(), world.getCurrency());
}
case "environment" -> {
return world.getEnvironment().toString().toLowerCase();
}
case "flight" -> {
return String.valueOf(world.getAllowFlight());
}
case "gamemode" -> {
return world.getGameMode().toString().toLowerCase();
}
case "generator" -> {
return world.getGenerator();
}
case "hunger" -> {
return String.valueOf(world.getHunger());
}
case "monstersspawn" -> {
return String.valueOf(world.canMonstersSpawn());
}
case "name" -> {
return world.getName();
}
case "playerlimit" -> {
return String.valueOf(world.getPlayerLimit());
}
case "price" -> {
return String.valueOf(world.getPrice());
}
case "pvp" -> {
return String.valueOf(world.isPVPEnabled());
}
case "seed" -> {
return String.valueOf(world.getSeed());
}
case "time" -> {
return world.getTime();
}
case "type" -> {
return world.getWorldType().toString().toLowerCase();
}
case "weather" -> {
return String.valueOf(world.isWeatherEnabled());
}
default -> {
warning("Unknown placeholder: " + placeholder);
return null;
}
}
}
}

View File

@ -0,0 +1,87 @@
package com.onarandombox.MultiverseCore.utils;
import co.aikar.locales.MessageKey;
import co.aikar.locales.MessageKeyProvider;
public enum MVCorei18n implements MessageKeyProvider {
// config status
CONFIG_SAVE_FAILED,
// check command
CHECK_CHECKING,
// clone command
CLONE_CLONING,
CLONE_FAILED,
CLONE_SUCCESS,
// create command
CREATE_PROPERTIES,
CREATE_PROPERTIES_ENVIRONMENT,
CREATE_PROPERTIES_SEED,
CREATE_PROPERTIES_WORLDTYPE,
CREATE_PROPERTIES_ADJUSTSPAWN,
CREATE_PROPERTIES_GENERATOR,
CREATE_PROPERTIES_STRUCTURES,
CREATE_LOADING,
CREATE_FAILED,
CREATE_SUCCESS,
// delete command
DELETE_DELETING,
DELETE_FAILED,
DELETE_SUCCESS,
DELETE_PROMPT,
// gamerule command
GAMERULE_FAILED,
GAMERULE_SUCCESS_SINGLE,
GAMERULE_SUCCESS_MULTIPLE,
// import command
IMPORT_IMPORTING,
IMPORT_FAILED,
IMPORT_SUCCESS,
// load command
LOAD_LOADING,
LOAD_FAILED,
LOAD_SUCCESS,
// regen command
REGEN_REGENERATING,
REGEN_FAILED,
REGEN_SUCCESS,
REGEN_PROMPT,
// reload command
RELOAD_RELOADING,
RELOAD_SUCCESS,
// remove command
REMOVE_FAILED,
REMOVE_SUCCESS,
// root MV command
ROOT_TITLE,
ROOT_HELP,
// teleport command
TELEPORT_SUCCESS,
// unload command
UNLOAD_UNLOADING,
UNLOAD_FAILURE,
UNLOAD_SUCCESS,
// debug command
DEBUG_INFO_OFF,
DEBUG_INFO_ON;
private final MessageKey key = MessageKey.of("mv-core." + this.name().replace('_', '.').toLowerCase());
@Override
public MessageKey getMessageKey() {
return this.key;
}
}

View File

@ -0,0 +1,59 @@
package com.onarandombox.MultiverseCore.utils.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import org.bukkit.plugin.Plugin;
/**
* A class loader that loads resources from the plugin's locales folder.
*/
public class FileResClassLoader extends ClassLoader {
private final transient File targetFolder;
/**
* Creates a new FileResClassLoader.
*
* @param plugin The plugin to load resources from.
* @param subFolder The subfolder to load resources from.
*/
public FileResClassLoader(final Plugin plugin, final String subFolder) {
super(plugin.getClass().getClassLoader());
this.targetFolder = new File(plugin.getDataFolder(), subFolder);
}
/**
* {@inheritDoc}
*/
@Override
public URL getResource(final String string) {
final File file = new File(targetFolder, string);
if (file.exists()) {
try {
return file.toURI().toURL();
} catch (final MalformedURLException ignored) {
}
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public InputStream getResourceAsStream(final String string) {
final File file = new File(targetFolder, string);
if (file.exists()) {
try {
return new FileInputStream(file);
} catch (final FileNotFoundException ignored) {
}
}
return null;
}
}

View File

@ -5,7 +5,7 @@
* with this project. * * with this project. *
******************************************************************************/ ******************************************************************************/
package com.onarandombox.MultiverseCore.utils; package com.onarandombox.MultiverseCore.utils.file;
import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES; import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;

View File

@ -0,0 +1,4 @@
/**
* This package contains all the classes that deal with files on disk.
*/
package com.onarandombox.MultiverseCore.utils.file;

View File

@ -31,7 +31,7 @@ import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.api.WorldPurger; import com.onarandombox.MultiverseCore.api.WorldPurger;
import com.onarandombox.MultiverseCore.event.MVWorldDeleteEvent; import com.onarandombox.MultiverseCore.event.MVWorldDeleteEvent;
import com.onarandombox.MultiverseCore.utils.FileUtils; import com.onarandombox.MultiverseCore.utils.file.FileUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameRule; import org.bukkit.GameRule;
import org.bukkit.Location; import org.bukkit.Location;

View File

@ -1,23 +1,116 @@
mv-core.config.save.failed=§cUnable to save Multiverse-Core config.yml. Your changes will be temporary! # configuration
mv-core.config.save.failed=Unable to save Multiverse-Core config.yml. Your changes will be temporary!
# /mv check
mv-core.check.description=Checks if a player can teleport to a destination.
mv-core.check.player.description=Player to check destination on.
mv-core.check.destination.description=A destination location, e.g. a world name.
mv-core.check.checking=Checking {player} to {destination} ..
# /mv clone
mv-core.clone.description=Clones a world.
mv-core.clone.world.description=The target world to clone.
mv-core.clone.newWorld.description=The new cloned world name.
mv-core.clone.cloning=Cloning world '{world}' to '{newworld}'...
mv-core.clone.failed=World could not be cloned! &fSee console for more details.
mv-core.clone.success=Cloned world '{world}'!
# /mv confirm
mv-core.confirm.description=Confirms dangerous commands before executing them.
# /mv create
mv-core.create.description=Creates a new world and loads it. mv-core.create.description=Creates a new world and loads it.
mv-core.create.name.description=New world name. mv-core.create.name.description=New world name.
mv-core.create.environment.description=The world's environment. See: /mv environments mv-core.create.environment.description=The world's environment. See: /mv environments
mv-core.create.flags.description=Additional world settings. See http://gg.gg/nn8bl for all possible flags. mv-core.create.flags.description=Additional world settings. See https://gg.gg/nn8bl for all possible flags.
mv-core.create.properties=Creating world {worldName} with the following properties: mv-core.create.properties=Creating world {worldName} with the following properties:
mv-core.create.properties.environment=- Environment: {environment} mv-core.create.properties.environment=- Environment: &f{environment}
mv-core.create.properties.seed=- Seed: {seed} mv-core.create.properties.seed=- Seed: &f{seed}
mv-core.create.properties.worldtype=- World Type: {worldType} mv-core.create.properties.worldtype=- World Type: &f{worldType}
mv-core.create.properties.adjustspawn=- Adjust Spawn: {adjustSpawn} mv-core.create.properties.adjustspawn=- Adjust Spawn: &f{adjustSpawn}
mv-core.create.properties.generator=- Generator: {generator} mv-core.create.properties.generator=- Generator: &f{generator}
mv-core.create.properties.structures=- Structures: {structures} mv-core.create.properties.structures=- Structures: &f{structures}
mv-core.create.loading=Creating world... mv-core.create.loading=Creating world...
mv-core.create.failed=§cFailed to create world '{worldName}'! See console for details. mv-core.create.failed=Failed to create world '{worldName}'! &fSee console for details.
mv-core.create.success=§aWorld '{worldName}' created successfully! mv-core.create.success=&aWorld '{worldName}' created successfully!
# /mv debug
mv-core.debug.info.description=Show the current debug level. mv-core.debug.info.description=Show the current debug level.
mv-core.debug.info.off=§fMultiverse Debug mode is §cOFF§f. mv-core.debug.info.off=&fMultiverse Debug mode is &cOFF&f.
mv-core.debug.info.on=§fMultiverse Debug mode is at §alevel {level}§f. mv-core.debug.info.on=&fMultiverse Debug mode is at &alevel {level}&f.
mv-core.debug.change.description=Change debug level. mv-core.debug.change.description=Change debug level.
mv-core.debug.change.syntax=level mv-core.debug.change.syntax=level
mv-core.debug.change.level.description=Debug level to set to. mv-core.debug.change.level.description=Debug level to set to.
# /mv delete
mv-core.delete.description=Deletes a world on your server PERMANENTLY.
mv-core.delete.deleting=Deleting world '{world}'...
mv-core.delete.failed=There was an issue deleting '{world}'! &fPlease check console for errors.
mv-core.delete.success=&aWorld {world} was deleted!
mv-core.delete.prompt=Are you sure you want to delete world '{world}'?
# /mv gamerule
mv-core.gamerule.description=Changes a gamerule in one or more worlds
mv-core.gamerule.gamerule.description=Gamerule to set
mv-core.gamerule.value.description=Value of gamerule
mv-core.gamerule.world.description=World to apply gamerule to, current world by default
mv-core.gamerule.failed=Failed to set gamerule {gamerule} to {value} in {world}. &fIt should be a {type}.
mv-core.gamerule.success.single=&aSuccessfully set {gamerule} to {value} in {world}.
mv-core.gamerule.success.multiple=&aSuccessfully set {gamerule} to {value} in {count} worlds.
# /mv import
mv-core.import.description=Imports an existing world folder.
mv-core.import.name.description=Name of the world folder.
mv-core.import.env.description=The world's environment. See: /mv env
mv-core.import.other.description=Other world settings. See: https://gg.gg/nn8c2
mv-core.import.importing=Starting import of world '{world}'...
mv-core.import.failed=Failed! &fSee console for more details.
mv-core.import.success=&aComplete!
# /mv load
mv-core.load.description=Loads a world. World must be already in worlds.yml, else please use /mv import.
mv-core.load.world.description=Name of world you want to load.
mv-core.load.loading=Loading world '{world}'...
mv-core.load.failed=Error trying to load world '{world}'!
mv-core.load.success=&aLoaded world '{world}'!
# /mv regen
mv-core.regen.description=Regenerates a world on your server. The previous state will be lost PERMANENTLY.
mv-core.regen.world.description=World that you want to regen.
mv-core.regen.other.description=Other world settings. See: http://gg.gg/nn8lk
mv-core.regen.regenerating=Regenerating world '{world}'...
mv-core.regen.failed=There was an issue regenerating '{world}'! &fPlease check console for errors.
mv-core.regen.success=&aWorld {world} was regenerated!
mv-core.regen.prompt=Are you sure you want to regenerate world '{world}'?
# /mv reload
mv-core.reload.description=Reloads config files for all Multiverse modules.
mv-core.reload.reloading=&6Reloading all Multiverse Plugin configs...
mv-core.reload.success=&aReload complete!
# /mv remove
mv-core.remove.description=Unloads a world from Multiverse and removes it from worlds.yml. This does NOT delete the world folder.
mv-core.remove.world.description=World you want to remove from MV's knowledge.
mv-core.remove.failed=Error trying to remove world from config!
mv-core.remove.success=&aWorld '{world}' is removed from config!
# /mv
mv-core.root.title=&a{name} version {version}
mv-core.root.help=&aSee &f/mv help&a for commands available.
# /mv tp
mv-core.teleport.description=Allows you to teleport to a location on your server!
mv-core.teleport.player.description=Target player to teleport.
mv-core.teleport.destination.description=Location, can be a world name.
mv-core.teleport.success=Teleporting {player} to {destination}...
# /mv unload
mv-core.unload.description=Unloads a world from Multiverse. This does NOT remove the world folder. This does NOT remove it from the config file.
mv-core.unload.world.description=Name of the world you want to unload.
mv-core.unload.unloading=Unloading world '{world}'...
mv-core.unload.failure=Error unloading world '{world}'! &fSee console for more details.
mv-core.unload.success=&aUnloaded world '{world}'!
# /mv usage
mv-core.usage.description=Show Multiverse-Core command usage.

View File

@ -2,6 +2,6 @@ name: Multiverse-Core
main: com.onarandombox.MultiverseCore.MultiverseCore main: com.onarandombox.MultiverseCore.MultiverseCore
authors: ['dumptruckman', 'Rigby', 'fernferret', 'lithium3141', 'main--'] authors: ['dumptruckman', 'Rigby', 'fernferret', 'lithium3141', 'main--']
website: 'https://dev.bukkit.org/projects/multiverse-core' website: 'https://dev.bukkit.org/projects/multiverse-core'
softdepend: ['Vault'] softdepend: ['Vault', 'PlaceholderAPI']
api-version: 1.13 api-version: 1.13
version: ${version} version: ${version}

View File

@ -1,5 +1,6 @@
package com.onarandombox.MultiverseCore.utils; package com.onarandombox.MultiverseCore.utils;
import com.onarandombox.MultiverseCore.utils.file.FileUtils;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;

View File

@ -20,6 +20,7 @@ import com.onarandombox.MultiverseCore.api.MVWorld;
import com.onarandombox.MultiverseCore.listeners.MVEntityListener; import com.onarandombox.MultiverseCore.listeners.MVEntityListener;
import com.onarandombox.MultiverseCore.listeners.MVPlayerListener; import com.onarandombox.MultiverseCore.listeners.MVPlayerListener;
import com.onarandombox.MultiverseCore.listeners.MVWeatherListener; import com.onarandombox.MultiverseCore.listeners.MVWeatherListener;
import com.onarandombox.MultiverseCore.utils.file.FileUtils;
import com.onarandombox.MultiverseCore.world.SimpleMVWorldManager; import com.onarandombox.MultiverseCore.world.SimpleMVWorldManager;
import junit.framework.Assert; import junit.framework.Assert;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;

View File

@ -0,0 +1,33 @@
package org.mvplugins.multiverse.core
import be.seeseemelk.mockbukkit.MockBukkit
import be.seeseemelk.mockbukkit.ServerMock
import com.onarandombox.MultiverseCore.MultiverseCore
import com.onarandombox.MultiverseCore.utils.TestingMode
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertNotNull
class MockBukkitTest {
lateinit var server: ServerMock
lateinit var plugin: MultiverseCore
@BeforeTest
fun setUp() {
TestingMode.enable()
server = MockBukkit.mock()
plugin = MockBukkit.load(MultiverseCore::class.java)
}
@AfterTest
fun tearDown() {
MockBukkit.unmock()
}
@Test
fun `MockBukkit loads the plugin`() {
assertNotNull(plugin)
}
}