diff --git a/src/main/java/org/mvplugins/multiverse/core/commands/SetSpawnCommand.java b/src/main/java/org/mvplugins/multiverse/core/commands/SetSpawnCommand.java new file mode 100644 index 000000000..d150d5a57 --- /dev/null +++ b/src/main/java/org/mvplugins/multiverse/core/commands/SetSpawnCommand.java @@ -0,0 +1,64 @@ +package org.mvplugins.multiverse.core.commands; + +import co.aikar.commands.BukkitCommandIssuer; +import co.aikar.commands.annotation.CommandAlias; +import co.aikar.commands.annotation.CommandPermission; +import co.aikar.commands.annotation.Description; +import co.aikar.commands.annotation.Optional; +import co.aikar.commands.annotation.Subcommand; +import co.aikar.commands.annotation.Syntax; +import io.vavr.control.Option; +import jakarta.inject.Inject; +import org.bukkit.Location; +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.world.WorldManager; + +@Service +@CommandAlias("mv") +public class SetSpawnCommand extends MultiverseCommand { + + private final WorldManager worldManager; + + @Inject + SetSpawnCommand( + @NotNull MVCommandManager commandManager, + @NotNull WorldManager worldManager) { + super(commandManager); + this.worldManager = worldManager; + } + + @CommandAlias("mvsetspawn") + @Subcommand("setspawn") + @CommandPermission("multiverse.core.spawn.set") + // @CommandCompletion("@location") // TODO: Use Brigadier to show above in chat like the vanilla TP command + @Syntax("[location]") + @Description("{@@mv-core.setspawn.description}") + void onSetSpawnCommand( + BukkitCommandIssuer issuer, + + @Optional + @Syntax("") + @Description("{@@mv-core.setspawn.location.description}") + Location location) { + Option.of(location).orElse(() -> { + if (issuer.isPlayer()) { + return Option.of(issuer.getPlayer().getLocation()); + } + return Option.none(); + }).peek(finalLocation -> + worldManager.getLoadedWorld(finalLocation.getWorld()) + .peek(mvWorld -> mvWorld.setSpawnLocation(finalLocation) + .onSuccess(ignore -> issuer.sendMessage( + "Successfully set spawn in " + mvWorld.getName() + " to " + prettyLocation(mvWorld.getSpawnLocation()))) + .onFailure(e -> issuer.sendMessage(e.getLocalizedMessage()))) + .onEmpty(() -> issuer.sendMessage("That world is not loaded or does not exist!")) + ).onEmpty(() -> issuer.sendMessage("You must specify a location in the format: worldname:x,y,z")); + } + + private String prettyLocation(Location location) { + return location.getX() + ", " + location.getY() + ", " + location.getZ(); + } +} diff --git a/src/main/java/org/mvplugins/multiverse/core/commands/SpawnCommand.java b/src/main/java/org/mvplugins/multiverse/core/commands/SpawnCommand.java new file mode 100644 index 000000000..97ff11e6c --- /dev/null +++ b/src/main/java/org/mvplugins/multiverse/core/commands/SpawnCommand.java @@ -0,0 +1,97 @@ +package org.mvplugins.multiverse.core.commands; + +import co.aikar.commands.BukkitCommandIssuer; +import co.aikar.commands.CommandIssuer; +import co.aikar.commands.MessageType; +import co.aikar.commands.annotation.*; +import com.dumptruckman.minecraft.util.Logging; +import jakarta.inject.Inject; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jvnet.hk2.annotations.Service; +import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer; +import org.mvplugins.multiverse.core.commandtools.MVCommandManager; +import org.mvplugins.multiverse.core.commandtools.MultiverseCommand; +import org.mvplugins.multiverse.core.teleportation.AsyncSafetyTeleporter; +import org.mvplugins.multiverse.core.utils.MVCorei18n; +import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld; +import org.mvplugins.multiverse.core.world.WorldManager; + +@Service +@CommandAlias("mv") +class SpawnCommand extends MultiverseCommand { + private final WorldManager worldManager; + private final AsyncSafetyTeleporter safetyTeleporter; + + @Inject + SpawnCommand(@NotNull MVCommandManager commandManager, + @NotNull WorldManager worldManager, + @NotNull AsyncSafetyTeleporter safetyTeleporter) { + super(commandManager); + this.worldManager = worldManager; + this.safetyTeleporter = safetyTeleporter; + } + + @CommandAlias("mvspawn") + @Subcommand("spawn") + @CommandCompletion("@players") + @Syntax("[player]") + @Description("{@@mv-core.spawn.description}") + void onSpawnTpCommand( + MVCommandIssuer issuer, + + @Flags("resolve=issuerAware") + @Syntax("[player]") + @Description("{@@mv-core.spawn.player.description}") + Player player) { + // TODO: Better handling of permission checking with CorePermissionsChecker + String permission = player.equals(issuer.getPlayer()) ? "multiverse.core.spawn.self" : "multiverse.core.spawn.other"; + if (!issuer.hasPermission(permission)) { + issuer.sendMessage("You do not have permission to use this command!"); + return; + } + + LoadedMultiverseWorld world = worldManager.getLoadedWorld(player.getWorld()).getOrNull(); + if (world == null) { + issuer.sendMessage("The world the player you are trying to teleport is in, is not a multiverse world"); + return; + } + + // Teleport the player + // TODO: Different message for teleporting self vs others + safetyTeleporter.teleportSafely(issuer.getIssuer(), player, world.getSpawnLocation()) + .onSuccess(() -> player.sendMessage(commandManager.formatMessage( + issuer, + MessageType.INFO, + MVCorei18n.SPAWN_SUCCESS, + "{teleporter}", + getTeleporterName(issuer, player) + ))) + .onFailure(failure -> { + issuer.sendError( + MVCorei18n.SPAWN_FAILED, + "{teleporter}", + getTeleporterName(issuer, player) + ); + issuer.sendError(failure.getFailureMessage()); + }); + + Logging.fine("Teleported " + player.getName() + " to " + world.getSpawnLocation().getX() + ", " + world.getSpawnLocation().getY() + ", " + world.getSpawnLocation().getZ()); + } + + private String getTeleporterName(BukkitCommandIssuer issuer, Player teleportTo) { + if (issuer.getIssuer().getName().equals("CONSOLE")) { + return commandManager.formatMessage(issuer, MessageType.INFO, MVCorei18n.SPAWN_CONSOLENAME); + } + if (issuer.getIssuer().getName().equals(teleportTo.getName())) { + return commandManager.formatMessage(issuer, MessageType.INFO, MVCorei18n.SPAWN_YOU); + } + return issuer.getIssuer().getName(); + } + + @Override + public boolean hasPermission(CommandIssuer issuer) { + // TODO: Fix autocomplete showing even if the player doesn't have permission + return issuer.hasPermission("multiverse.core.spawn.self") || issuer.hasPermission("multiverse.core.spawn.other"); + } +} diff --git a/src/main/java/org/mvplugins/multiverse/core/utils/MVCorei18n.java b/src/main/java/org/mvplugins/multiverse/core/utils/MVCorei18n.java index 8d089b984..2707a2ce3 100644 --- a/src/main/java/org/mvplugins/multiverse/core/utils/MVCorei18n.java +++ b/src/main/java/org/mvplugins/multiverse/core/utils/MVCorei18n.java @@ -94,6 +94,14 @@ public enum MVCorei18n implements MessageKeyProvider { ROOT_TITLE, ROOT_HELP, + // spawn tp command + SPAWN_DESCRIPTION, + SPAWN_PLAYER_DESCRIPTION, + SPAWN_SUCCESS, + SPAWN_FAILED, + SPAWN_CONSOLENAME, + SPAWN_YOU, + // teleport command TELEPORT_SUCCESS, diff --git a/src/main/resources/multiverse-core_en.properties b/src/main/resources/multiverse-core_en.properties index 8e2f4b5a1..2f7ea5579 100644 --- a/src/main/resources/multiverse-core_en.properties +++ b/src/main/resources/multiverse-core_en.properties @@ -124,6 +124,18 @@ mv-core.remove.success=&aWorld '{world}' removed! mv-core.root.title=&a{name} version {version} mv-core.root.help=&aSee &f/mv help&a for commands available. +# /mv setspawn +mv-core.setspawn.description=Sets the spawn location of the specified world +mv-core.setspawn.location.description=Location of the new spawn +mv-core.setspawn.world.description=Target world to set spawn of (defaults to player's current world) + +# /mv spawn +mv-core.spawn.description=Teleports the specified player to the spawn of the world they are in +mv-core.spawn.player.description=The player +mv-core.spawn.success={teleporter} just sent you to spawn! +mv-core.spawn.consolename=The console +mv-core.spawn.you=You + # /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.