migrate all commands to brig

This commit is contained in:
2024-11-27 20:18:22 +01:00
parent f71153e266
commit 50d1d83612
9 changed files with 243 additions and 367 deletions
@@ -1,20 +1,30 @@
package me.youhavetrouble.blockedit; package me.youhavetrouble.blockedit;
import com.mojang.brigadier.Command; import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.DoubleArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.LiteralCommandNode;
import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.command.brigadier.Commands; import io.papermc.paper.command.brigadier.Commands;
import io.papermc.paper.command.brigadier.argument.ArgumentTypes;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
import me.youhavetrouble.blockedit.api.BlockEditAPI; import me.youhavetrouble.blockedit.api.BlockEditAPI;
import me.youhavetrouble.blockedit.operations.PasteOperation;
import me.youhavetrouble.blockedit.operations.ReplaceOperation;
import me.youhavetrouble.blockedit.operations.SetOperation;
import me.youhavetrouble.blockedit.util.Selection;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
@SuppressWarnings("UnstableApiUsage") @SuppressWarnings("UnstableApiUsage")
public class BlockEditCommands { public class BlockEditCommands {
@@ -27,6 +37,47 @@ public class BlockEditCommands {
wandCommand(), wandCommand(),
"Gives the player chosen wand" "Gives the player chosen wand"
); );
commands.register(
copyCommand(),
"Copies the selected area to the clipboard"
);
commands.register(
pasteCommand(),
"Pastes the clipboard at the player's location"
);
commands.register(
deselCommand(),
"Resets the player's selection"
);
commands.register(
pos1Command(),
"Sets the first point of the player's selection"
);
commands.register(
pos2Command(),
"Sets the second point of the player's selection"
);
commands.register(
rotateCommand(),
"Rotates the clipboard by the specified angle"
);
commands.register(
setCommand(),
"Sets the selected area to the specified block"
);
commands.register(
replaceCommand(),
"Replaces the specified block with another block"
);
}); });
} }
@@ -76,4 +127,196 @@ public class BlockEditCommands {
.build(); .build();
} }
private static LiteralCommandNode<CommandSourceStack> copyCommand() {
return Commands.literal("copy")
.requires(css -> {
if (!(css.getSender() instanceof Player player)) return false;
return player.hasPermission("blockedit.command.copy");
})
.executes(ctx -> {
if (!(ctx.getSource().getSender() instanceof Player player)) {
ctx.getSource().getSender().sendMessage(Component.text("Only players can use this command", NamedTextColor.RED));
return Command.SINGLE_SUCCESS;
}
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
try {
bePlayer.setClipboardFromSelection();
player.sendMessage(Component.text("Copied selection to clipboard"));
} catch (IllegalStateException e) {
player.sendMessage(Component.text("You need to select an area first"));
}
return Command.SINGLE_SUCCESS;
})
.build();
}
private static LiteralCommandNode<CommandSourceStack> deselCommand() {
return Commands.literal("desel")
.requires(css -> {
if (!(css.getSender() instanceof Player player)) return false;
return player.hasPermission("blockedit.command.desel");
})
.executes(ctx -> {
if (!(ctx.getSource().getSender() instanceof Player player)) {
ctx.getSource().getSender().sendMessage(Component.text("Only players can use this command", NamedTextColor.RED));
return Command.SINGLE_SUCCESS;
}
BEPlayer.getByPlayer(player).resetSelection();
player.sendMessage(Component.text("You have reset your selection"));
return Command.SINGLE_SUCCESS;
})
.build();
}
private static LiteralCommandNode<CommandSourceStack> pos1Command() {
return Commands.literal("pos1")
.requires(css -> {
if (!(css.getSender() instanceof Player player)) return false;
return player.hasPermission("blockedit.command.pos");
})
.executes(ctx -> {
if (!(ctx.getSource().getSender() instanceof Player player)) {
ctx.getSource().getSender().sendMessage(Component.text("Only players can use this command", NamedTextColor.RED));
return Command.SINGLE_SUCCESS;
}
BEPlayer.getByPlayer(player).setSelectionPoint1(player.getLocation().toBlockLocation());
player.sendMessage(Component.text("First point set at your location"));
return Command.SINGLE_SUCCESS;
})
.build();
}
private static LiteralCommandNode<CommandSourceStack> pos2Command() {
return Commands.literal("pos2")
.requires(css -> {
if (!(css.getSender() instanceof Player player)) return false;
return player.hasPermission("blockedit.command.pos");
})
.executes(ctx -> {
if (!(ctx.getSource().getSender() instanceof Player player)) {
ctx.getSource().getSender().sendMessage(Component.text("Only players can use this command", NamedTextColor.RED));
return Command.SINGLE_SUCCESS;
}
BEPlayer.getByPlayer(player).setSelectionPoint2(player.getLocation().toBlockLocation());
player.sendMessage(Component.text("Second point set at your location"));
return Command.SINGLE_SUCCESS;
})
.build();
}
private static LiteralCommandNode<CommandSourceStack> pasteCommand() {
return Commands.literal("paste")
.requires(css -> {
if (!(css.getSender() instanceof Player player)) return false;
return player.hasPermission("blockedit.command.paste");
})
.executes(ctx -> {
if (!(ctx.getSource().getSender() instanceof Player player)) {
ctx.getSource().getSender().sendMessage(Component.text("Only players can use this command", NamedTextColor.RED));
return Command.SINGLE_SUCCESS;
}
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
Vector playerLocationVector = player.getLocation().toBlockLocation().toVector();
HashMap<Vector, BlockState> absoluteBlocks = new HashMap<>(bePlayer.getClipboard().getBlocks().size());
bePlayer.getClipboard().getBlocks().forEach((vector, blockState) -> {
Vector absolutePosition = vector.clone().add(playerLocationVector);
absoluteBlocks.put(absolutePosition, blockState);
});
Selection selection = Selection.fromClipboard(absoluteBlocks.keySet(), player.getWorld());
BlockEditAPI.runOperation(selection, 1, new PasteOperation(absoluteBlocks));
player.sendMessage(Component.text("Pasting clipboard..."));
return Command.SINGLE_SUCCESS;
})
.build();
}
private static LiteralCommandNode<CommandSourceStack> rotateCommand() {
return Commands.literal("rotate")
.requires(css -> {
if (!(css.getSender() instanceof Player player)) return false;
return player.hasPermission("blockedit.command.rotate");
})
.then(
Commands.argument("angle", DoubleArgumentType.doubleArg(-360, 360))
.executes(ctx -> {
if (!(ctx.getSource().getSender() instanceof Player player)) {
ctx.getSource().getSender().sendMessage(Component.text("Only players can use this command", NamedTextColor.RED));
return Command.SINGLE_SUCCESS;
}
double angle = ctx.getArgument("angle", Double.class);
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
bePlayer.getClipboard().rotate(angle);
player.sendMessage(Component.text("Rotated clipboard by " + angle + " degrees"));
return Command.SINGLE_SUCCESS;
})
)
.build();
}
private static LiteralCommandNode<CommandSourceStack> setCommand() {
return Commands.literal("set")
.requires(css -> {
if (!(css.getSender() instanceof Player player)) return false;
return player.hasPermission("blockedit.command.set");
})
.then(
// TODO replace with better way to provide block data, possibly multiple arguments
Commands.argument("block", ArgumentTypes.blockState())
.executes(ctx -> {
if (!(ctx.getSource().getSender() instanceof Player player)) {
ctx.getSource().getSender().sendMessage(Component.text("Only players can use this command", NamedTextColor.RED));
return Command.SINGLE_SUCCESS;
}
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
BlockState blockState = ctx.getArgument("block", BlockState.class);
Selection selection = bePlayer.getSelection();
BlockEditAPI.runOperation(selection, 1, new SetOperation(blockState.getBlockData()));
player.sendMessage(Component.text("Setting blocks..."));
return Command.SINGLE_SUCCESS;
})
)
.build();
}
private static LiteralCommandNode<CommandSourceStack> replaceCommand() {
return Commands.literal("replace")
.requires(css -> {
if (!(css.getSender() instanceof Player player)) return false;
return player.hasPermission("blockedit.command.replace");
})
.then(
// TODO replace with better way to provide block data, possibly multiple arguments
Commands.argument("to_replace", ArgumentTypes.blockState())
.then(Commands.argument("replace_with", ArgumentTypes.blockState())
.executes(ctx -> {
if (!(ctx.getSource().getSender() instanceof Player player)) {
ctx.getSource().getSender().sendMessage(Component.text("Only players can use this command", NamedTextColor.RED));
return Command.SINGLE_SUCCESS;
}
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
BlockState toReplace = ctx.getArgument("to_replace", BlockState.class);
BlockState replaceWith = ctx.getArgument("replace_with", BlockState.class);
Selection selection = bePlayer.getSelection();
BlockEditAPI.runOperation(selection, 1, new ReplaceOperation(toReplace.getBlockData(), replaceWith.getBlockData()));
player.sendMessage(Component.text("Replacing blocks..."));
return Command.SINGLE_SUCCESS;
})
)
)
.build();
}
} }
@@ -1,29 +0,0 @@
package me.youhavetrouble.blockedit.commands;
import me.youhavetrouble.blockedit.BEPlayer;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class CopyCommand extends Command {
public CopyCommand() {
super("copy");
setPermission("blockedit.command.copy");
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) {
if (!(sender instanceof Player player)) return true;
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
try {
bePlayer.setClipboardFromSelection();
player.sendMessage(Component.text("Copied selection to clipboard"));
} catch (IllegalStateException e) {
player.sendMessage(Component.text("You need to select an area first"));
}
return true;
}
}
@@ -1,24 +0,0 @@
package me.youhavetrouble.blockedit.commands;
import me.youhavetrouble.blockedit.BEPlayer;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class DeselCommand extends Command {
public DeselCommand() {
super("desel");
setPermission("blockedit.command.desel");
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player player)) return true;
BEPlayer.getByPlayer(player).resetSelection();
player.sendMessage(Component.text("You have reset your selection"));
return true;
}
}
@@ -1,47 +0,0 @@
package me.youhavetrouble.blockedit.commands;
import me.youhavetrouble.blockedit.BEPlayer;
import me.youhavetrouble.blockedit.api.BlockEditAPI;
import me.youhavetrouble.blockedit.operations.PasteOperation;
import me.youhavetrouble.blockedit.util.Selection;
import net.kyori.adventure.text.Component;
import org.bukkit.block.BlockState;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
public class PasteCommand extends Command {
public PasteCommand() {
super("paste");
setPermission("blockedit.command.paste");
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage(Component.text("You need to be a player to do this"));
return true;
}
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
Vector playerLocationVector = player.getLocation().toBlockLocation().toVector();
HashMap<Vector, BlockState> absoluteBlocks = new HashMap<>(bePlayer.getClipboard().getBlocks().size());
bePlayer.getClipboard().getBlocks().forEach((vector, blockState) -> {
Vector absolutePosition = vector.clone().add(playerLocationVector);
absoluteBlocks.put(absolutePosition, blockState);
});
Selection selection = Selection.fromClipboard(absoluteBlocks.keySet(), player.getWorld());
BlockEditAPI.runOperation(selection, 1, new PasteOperation(absoluteBlocks));
player.sendMessage(Component.text("Pasting clipboard..."));
return false;
}
}
@@ -1,25 +0,0 @@
package me.youhavetrouble.blockedit.commands;
import me.youhavetrouble.blockedit.BEPlayer;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class Pos1Command extends Command {
public Pos1Command() {
super("pos1");
setPermission("blockedit.command.pos");
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player player)) return true;
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
bePlayer.setSelectionPoint1(player.getLocation().toBlockLocation());
player.sendMessage(Component.text("First point set at your location"));
return true;
}
}
@@ -1,24 +0,0 @@
package me.youhavetrouble.blockedit.commands;
import me.youhavetrouble.blockedit.BEPlayer;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class Pos2Command extends Command {
public Pos2Command() {
super("pos2");
setPermission("blockedit.command.pos");
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player player)) return true;
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
bePlayer.setSelectionPoint2(player.getLocation().toBlockLocation());
player.sendMessage(Component.text("Second point set at your location"));
return true;
}
}
@@ -1,87 +0,0 @@
package me.youhavetrouble.blockedit.commands;
import me.youhavetrouble.blockedit.BEPlayer;
import me.youhavetrouble.blockedit.api.BlockEditAPI;
import me.youhavetrouble.blockedit.commands.arguments.BlockDataArgument;
import me.youhavetrouble.blockedit.commands.arguments.InvalidDataException;
import me.youhavetrouble.blockedit.commands.arguments.InvalidMaterialException;
import me.youhavetrouble.blockedit.operations.ReplaceOperation;
import me.youhavetrouble.blockedit.util.Selection;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class ReplaceCommand extends Command {
public ReplaceCommand() {
super("replace");
setPermission("blockedit.command.replace");
}
@Override
public @NotNull List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
if (args.length == 1 || args.length == 2) {
ArrayList<String> suggestions = new ArrayList<>();
for (Material material : Material.values()) {
if (material.isBlock()) suggestions.add(material.name().toLowerCase());
}
return StringUtil.copyPartialMatches(args[args.length-1], suggestions, new ArrayList<>());
}
return new ArrayList<>();
}
@Override
public boolean execute(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] args) {
if (!(commandSender instanceof Player player)) return true;
if (args.length == 0) {
player.sendMessage(Component.text("You need to provide block type"));
return true;
}
if (args.length < 2) {
player.sendMessage(Component.text("You need to provide block type to replace"));
return true;
}
BlockData blockData = null;
BlockData blockDataToReplaceWith = null;
try {
blockData = BlockDataArgument.getBlockData(args[0]);
} catch (InvalidMaterialException e) {
player.sendMessage(Component.text("Provided block type does not exist"));
return true;
} catch (InvalidDataException e) {
player.sendMessage(Component.text("Provided block data is invalid"));
return true;
}
try {
blockDataToReplaceWith = BlockDataArgument.getBlockData(args[1]);
} catch (InvalidMaterialException e) {
player.sendMessage(Component.text("Provided block type does not exist"));
return true;
} catch (InvalidDataException e) {
player.sendMessage(Component.text("Provided block data is invalid"));
return true;
}
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
Selection selection = bePlayer.getSelection();
if (selection == null) {
player.sendMessage(Component.text("You need to select 2 points to do this"));
return true;
}
BlockEditAPI.runOperation(selection, 1, new ReplaceOperation(blockData, blockDataToReplaceWith));
player.sendMessage(Component.text("Replacing blocks..."));
return true;
}
}
@@ -1,52 +0,0 @@
package me.youhavetrouble.blockedit.commands;
import me.youhavetrouble.blockedit.BEPlayer;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class RotateCommand extends Command {
public RotateCommand() {
super("rotate");
setPermission("blockedit.command.rotate");
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage(Component.text("You need to be a player to use this command"));
return true;
}
if (args.length == 0) {
player.sendMessage(Component.text("You need to provide an angle"));
return true;
}
double angle;
try {
angle = Double.parseDouble(args[0]);
} catch (NumberFormatException e) {
player.sendMessage(Component.text("Angle must be a number"));
return true;
}
if (angle > 360 || angle < -360) {
player.sendMessage(Component.text("Angle must be between -360 and 360"));
return true;
}
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
bePlayer.getClipboard().rotate(angle);
player.sendMessage(Component.text("Rotated clipboard by " + angle + " degrees"));
return false;
}
}
@@ -1,79 +0,0 @@
package me.youhavetrouble.blockedit.commands;
import me.youhavetrouble.blockedit.BEPlayer;
import me.youhavetrouble.blockedit.api.BlockEditAPI;
import me.youhavetrouble.blockedit.commands.arguments.BlockDataArgument;
import me.youhavetrouble.blockedit.commands.arguments.InvalidDataException;
import me.youhavetrouble.blockedit.commands.arguments.InvalidMaterialException;
import me.youhavetrouble.blockedit.operations.SetOperation;
import me.youhavetrouble.blockedit.util.Selection;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class SetCommand extends Command {
public SetCommand() {
super("set");
setPermission("blockedit.command.set");
}
@Override
public @NotNull List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
ArrayList<String> suggestions = new ArrayList<>();
if (args.length == 1) {
for (Material material : Material.values()) {
if (material.isBlock())
suggestions.add(material.name().toLowerCase());
}
return StringUtil.copyPartialMatches(args[0], suggestions, new ArrayList<>());
}
return suggestions;
}
@Override
public boolean execute(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] args) {
if (!(commandSender instanceof Player player)) return true;
BEPlayer bePlayer = BEPlayer.getByPlayer(player);
Selection selection = bePlayer.getSelection();
if (selection == null) {
player.sendMessage(Component.text("You need to select 2 points to do this"));
return true;
}
if (args.length != 1) {
return false;
}
BlockData blockData;
try {
blockData = BlockDataArgument.getBlockData(args[0]);
} catch (InvalidMaterialException e) {
player.sendMessage(Component.text("Provided block type does not exist"));
return true;
} catch (InvalidDataException e) {
player.sendMessage(Component.text("Provided block data is invalid"));
return true;
}
BlockEditAPI.runOperation(selection, 1, new SetOperation(blockData));
player.sendMessage(Component.text("Setting blocks..."));
return true;
}
@Override
public @NotNull String getUsage() {
return "/set <block[block=data]>";
}
}