Refactor PlayerShopCommand to use Brigadier.
This commit is contained in:
parent
aaebd64294
commit
4d531ea7b5
|
|
@ -1,6 +1,6 @@
|
||||||
package com.alttd.playershops;
|
package com.alttd.playershops;
|
||||||
|
|
||||||
import com.alttd.playershops.commands.PlayerShopCommands;
|
import com.alttd.playershops.commands.PlayerShopCommand;
|
||||||
import com.alttd.playershops.config.Config;
|
import com.alttd.playershops.config.Config;
|
||||||
import com.alttd.playershops.config.DatabaseConfig;
|
import com.alttd.playershops.config.DatabaseConfig;
|
||||||
import com.alttd.playershops.config.MessageConfig;
|
import com.alttd.playershops.config.MessageConfig;
|
||||||
|
|
@ -10,12 +10,18 @@ import com.alttd.playershops.listener.*;
|
||||||
import com.alttd.playershops.shop.ShopType;
|
import com.alttd.playershops.shop.ShopType;
|
||||||
import com.alttd.playershops.storage.database.DatabaseManager;
|
import com.alttd.playershops.storage.database.DatabaseManager;
|
||||||
import com.alttd.playershops.storage.database.DatabaseHelper;
|
import com.alttd.playershops.storage.database.DatabaseHelper;
|
||||||
|
import io.papermc.paper.command.brigadier.Commands;
|
||||||
|
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
|
||||||
|
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.milkbowl.vault.economy.Economy;
|
import net.milkbowl.vault.economy.Economy;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class PlayerShops extends JavaPlugin {
|
public class PlayerShops extends JavaPlugin {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
|
@ -107,7 +113,11 @@ public class PlayerShops extends JavaPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommands() {
|
private void registerCommands() {
|
||||||
PlayerShopCommands.registerCommands();
|
LifecycleEventManager<Plugin> manager = this.getLifecycleManager();
|
||||||
|
manager.registerEventHandler(LifecycleEvents.COMMANDS, event -> {
|
||||||
|
final Commands commands = event.registrar();
|
||||||
|
commands.register(new PlayerShopCommand().command(), null, List.of("shop", "shops"));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reloadConfigs() {
|
public void reloadConfigs() {
|
||||||
|
|
|
||||||
|
|
@ -1,147 +1,96 @@
|
||||||
package com.alttd.playershops.commands;
|
package com.alttd.playershops.commands;
|
||||||
|
|
||||||
|
import com.alttd.playershops.PlayerShops;
|
||||||
|
import com.alttd.playershops.commands.arguments.OfflinePlayerArgument;
|
||||||
import com.alttd.playershops.commands.subcommands.CheckStockCommand;
|
import com.alttd.playershops.commands.subcommands.CheckStockCommand;
|
||||||
import com.alttd.playershops.commands.subcommands.ReloadCommand;
|
|
||||||
import com.alttd.playershops.commands.subcommands.TransferShopsCommand;
|
|
||||||
import com.alttd.playershops.gui.HomeGui;
|
import com.alttd.playershops.gui.HomeGui;
|
||||||
import com.alttd.playershops.utils.Util;
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
import it.unimi.dsi.fastutil.Pair;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import org.bukkit.Bukkit;
|
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||||
import org.bukkit.Location;
|
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||||
import org.bukkit.command.Command;
|
import io.papermc.paper.command.brigadier.Commands;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.permissions.Permission;
|
|
||||||
import org.bukkit.permissions.PermissionDefault;
|
|
||||||
import org.bukkit.plugin.PluginManager;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.*;
|
public class PlayerShopCommand {
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static net.kyori.adventure.text.Component.text;
|
public static final String BASE_PERM = "playershops.command";
|
||||||
import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
|
||||||
|
|
||||||
public class PlayerShopCommand extends Command {
|
public @NotNull LiteralCommandNode<CommandSourceStack> command() {
|
||||||
|
final LiteralArgumentBuilder<CommandSourceStack> builder =
|
||||||
|
Commands.literal("playershop")
|
||||||
|
.requires(
|
||||||
|
commandSourceStack -> commandSourceStack.getSender().hasPermission(BASE_PERM)
|
||||||
|
&& commandSourceStack.getSender() instanceof Player
|
||||||
|
)
|
||||||
|
.executes((source) -> {
|
||||||
|
if (!(source.getSource().getSender() instanceof Player player))
|
||||||
|
return 1;
|
||||||
|
|
||||||
public static final String BASE_PERM = "playershops.command"; // TODO load from config
|
// TODO -- DIALOG
|
||||||
|
HomeGui gui = new HomeGui(player.getUniqueId());
|
||||||
|
gui.open();
|
||||||
|
return 1;
|
||||||
|
})
|
||||||
|
.then(
|
||||||
|
Commands.literal("reload")
|
||||||
|
.requires(commandSourceStack -> commandSourceStack.getSender().hasPermission(BASE_PERM + "reload"))
|
||||||
|
.executes(source -> {
|
||||||
|
PlayerShops.getInstance().reloadConfigs();
|
||||||
|
return 1;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
Commands.literal("checkstock")
|
||||||
|
.requires(commandSourceStack -> commandSourceStack.getSender().hasPermission(BASE_PERM + "checkstock")
|
||||||
|
&& commandSourceStack.getSender() instanceof Player)
|
||||||
|
.then(
|
||||||
|
Commands.argument("range", IntegerArgumentType.integer(1, 100))
|
||||||
|
.executes(source -> {
|
||||||
|
if (!(source.getSource().getSender() instanceof Player player))
|
||||||
|
return 1;
|
||||||
|
|
||||||
// subcommand label -> subcommand
|
int range = source.getArgument("range", Integer.class);
|
||||||
private static final Map<String, Subcommand> SUBCOMMANDS = PlayerShopCommands.make(() -> {
|
int stock = -1;
|
||||||
final Map<Set<String>, Subcommand> commands = new HashMap<>();
|
CheckStockCommand.doStockCheck(player, range, stock);
|
||||||
|
return 1;
|
||||||
|
})
|
||||||
|
.then(
|
||||||
|
Commands.argument("stock", IntegerArgumentType.integer())
|
||||||
|
.executes(source -> {
|
||||||
|
if (!(source.getSource().getSender() instanceof Player player))
|
||||||
|
return 1;
|
||||||
|
|
||||||
commands.put(Set.of("reload"), new ReloadCommand());
|
int range = source.getArgument("range", Integer.class);
|
||||||
commands.put(Set.of("checkstock"), new CheckStockCommand());
|
int stock = source.getArgument("stock", Integer.class);
|
||||||
commands.put(Set.of("transfershops"), new TransferShopsCommand());
|
CheckStockCommand.doStockCheck(player, range, stock);
|
||||||
|
return 1;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
Commands.literal("transfershops")
|
||||||
|
.requires(commandSourceStack -> commandSourceStack.getSender().hasPermission(BASE_PERM + "transfershops"))
|
||||||
|
.then(
|
||||||
|
Commands.argument("old", new OfflinePlayerArgument())
|
||||||
|
.then(
|
||||||
|
Commands.argument("new", new OfflinePlayerArgument())
|
||||||
|
)
|
||||||
|
.executes(
|
||||||
|
source -> {
|
||||||
|
OfflinePlayer oldOwner = source.getArgument("old", OfflinePlayer.class);
|
||||||
|
OfflinePlayer newOwner = source.getArgument("new", OfflinePlayer.class);
|
||||||
|
PlayerShops.getInstance().getShopHandler().transferShops(source.getSource().getSender(), oldOwner, newOwner);
|
||||||
|
|
||||||
return commands.entrySet().stream()
|
return 1;
|
||||||
.flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue())))
|
}
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
)
|
||||||
});
|
)
|
||||||
// alias -> subcommand label
|
)
|
||||||
private static final Map<String, String> ALIASES = PlayerShopCommands.make(() -> {
|
;
|
||||||
final Map<String, Set<String>> aliases = new HashMap<>();
|
return builder.build();
|
||||||
|
|
||||||
aliases.put("reload", Set.of("reloadconfig"));
|
|
||||||
|
|
||||||
return aliases.entrySet().stream()
|
|
||||||
.flatMap(entry -> entry.getValue().stream().map(s -> Map.entry(s, entry.getKey())))
|
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
|
||||||
});
|
|
||||||
|
|
||||||
public PlayerShopCommand() {
|
|
||||||
super("playershop");
|
|
||||||
this.description = "PlayerShop related commands";
|
|
||||||
this.usageMessage = "/playershop [" + String.join(" | ", SUBCOMMANDS.keySet()) + "]";
|
|
||||||
this.setAliases(List.of("shop", "shops"));
|
|
||||||
final List<String> permissions = new ArrayList<>();
|
|
||||||
permissions.add(BASE_PERM);
|
|
||||||
permissions.addAll(SUBCOMMANDS.keySet().stream().map(s -> BASE_PERM + "." + s).toList());
|
|
||||||
this.setPermission(String.join(";", permissions));
|
|
||||||
final PluginManager pluginManager = Bukkit.getServer().getPluginManager();
|
|
||||||
for (final String perm : permissions) {
|
|
||||||
pluginManager.addPermission(new Permission(perm, PermissionDefault.OP));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean testPermission(final CommandSender sender, final String permission) {
|
|
||||||
if (sender.hasPermission(BASE_PERM + "." + permission)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
sender.sendMessage(Bukkit.permissionMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull List<String> tabComplete(
|
|
||||||
final @NotNull CommandSender sender,
|
|
||||||
final @NotNull String alias,
|
|
||||||
final String[] args,
|
|
||||||
final @Nullable Location location
|
|
||||||
) throws IllegalArgumentException {
|
|
||||||
if (args.length <= 1) {
|
|
||||||
return PlayerShopCommands.getListMatchingLast(sender, args, SUBCOMMANDS.keySet(), BASE_PERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
final @Nullable Pair<String, Subcommand> subCommand = resolveCommand(args[0]);
|
|
||||||
if (subCommand != null) {
|
|
||||||
return subCommand.second().tabComplete(sender, subCommand.first(), Arrays.copyOfRange(args, 1, args.length));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean execute(
|
|
||||||
final @NotNull CommandSender sender,
|
|
||||||
final @NotNull String commandLabel,
|
|
||||||
final String[] args
|
|
||||||
) {
|
|
||||||
if (!testPermission(sender)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length == 0) {
|
|
||||||
if (!(sender instanceof Player player)) {
|
|
||||||
sender.sendMessage(Util.parseMiniMessage("<red>Only players can use this command."));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
HomeGui gui = new HomeGui(player.getUniqueId());
|
|
||||||
gui.open();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
final @Nullable Pair<String, Subcommand> subCommand = resolveCommand(args[0]);
|
|
||||||
|
|
||||||
if (subCommand == null) {
|
|
||||||
sender.sendMessage(text("Usage: " + this.usageMessage, RED));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!testPermission(sender, subCommand.first())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
final String[] choppedArgs = Arrays.copyOfRange(args, 1, args.length);
|
|
||||||
return subCommand.second().execute(sender, subCommand.first(), choppedArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static @Nullable Pair<String, Subcommand> resolveCommand(String label) {
|
|
||||||
label = label.toLowerCase(Locale.ENGLISH);
|
|
||||||
@Nullable Subcommand subCommand = SUBCOMMANDS.get(label);
|
|
||||||
if (subCommand == null) {
|
|
||||||
final @Nullable String command = ALIASES.get(label);
|
|
||||||
if (command != null) {
|
|
||||||
label = command;
|
|
||||||
subCommand = SUBCOMMANDS.get(command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subCommand != null) {
|
|
||||||
return Pair.of(label, subCommand);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
package com.alttd.playershops.commands;
|
|
||||||
|
|
||||||
import com.google.common.base.Functions;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public class PlayerShopCommands {
|
|
||||||
|
|
||||||
private PlayerShopCommands() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<String, Command> COMMANDS = new HashMap<>();
|
|
||||||
static {
|
|
||||||
COMMANDS.put("playershop", new PlayerShopCommand());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void registerCommands() {
|
|
||||||
COMMANDS.forEach((s, command) -> {
|
|
||||||
Bukkit.getCommandMap().register(s, command.getName(), command);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Code from Mojang - copyright them | Altered to fit our needs
|
|
||||||
public static List<String> getListMatchingLast(final CommandSender sender, final String[] args, final String basePermission, final String... matches) {
|
|
||||||
return getListMatchingLast(sender, args, Arrays.asList(matches), basePermission);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean matches(final String s, final String s1) {
|
|
||||||
return s1.regionMatches(true, 0, s, 0, s.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> getListMatchingLast(final CommandSender sender, final String[] strings, final Collection<?> collection, final String basePermission) {
|
|
||||||
String last = strings[strings.length - 1];
|
|
||||||
ArrayList<String> results = Lists.newArrayList();
|
|
||||||
|
|
||||||
if (!collection.isEmpty()) {
|
|
||||||
|
|
||||||
for (String s1 : collection.stream().map(Functions.toStringFunction()).toList()) {
|
|
||||||
if (matches(last, s1) && (sender.hasPermission(basePermission + "." + s1))) {
|
|
||||||
results.add(s1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T make(Supplier<T> factory) {
|
|
||||||
return factory.get();
|
|
||||||
}
|
|
||||||
// end copy stuff
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
package com.alttd.playershops.commands;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@DefaultQualifier(NonNull.class)
|
|
||||||
public interface Subcommand {
|
|
||||||
|
|
||||||
boolean execute(CommandSender sender, String subCommand, String[] args);
|
|
||||||
|
|
||||||
default List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.alttd.playershops.commands.arguments;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.Message;
|
||||||
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
|
import io.papermc.paper.command.brigadier.MessageComponentSerializer;
|
||||||
|
import io.papermc.paper.command.brigadier.argument.CustomArgumentType;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public class OfflinePlayerArgument implements CustomArgumentType.Converted<OfflinePlayer, String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull OfflinePlayer convert(String nativeType) throws CommandSyntaxException {
|
||||||
|
try {
|
||||||
|
return Bukkit.getOfflinePlayer(nativeType);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Message message = MessageComponentSerializer.message().serialize(Component.text("Invalid PlayerName %s!".formatted(nativeType), NamedTextColor.RED));
|
||||||
|
|
||||||
|
throw new CommandSyntaxException(new SimpleCommandExceptionType(message), message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ArgumentType<String> getNativeType() {
|
||||||
|
return StringArgumentType.word();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <S> @NotNull CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
||||||
|
Bukkit.getOnlinePlayers().stream()
|
||||||
|
.map(Player::getName)
|
||||||
|
.filter(name -> name.toLowerCase(Locale.ROOT).startsWith(builder.getRemainingLowerCase()))
|
||||||
|
.forEach(builder::suggest);
|
||||||
|
return builder.buildFuture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,7 @@ package com.alttd.playershops.commands.subcommands;
|
||||||
|
|
||||||
import com.alttd.playershops.PlayerShops;
|
import com.alttd.playershops.PlayerShops;
|
||||||
import com.alttd.playershops.commands.PlayerShopCommand;
|
import com.alttd.playershops.commands.PlayerShopCommand;
|
||||||
import com.alttd.playershops.commands.PlayerShopCommands;
|
import com.alttd.playershops.config.MessageConfig;
|
||||||
import com.alttd.playershops.commands.Subcommand;
|
|
||||||
import com.alttd.playershops.shop.PlayerShop;
|
import com.alttd.playershops.shop.PlayerShop;
|
||||||
import com.alttd.playershops.utils.ShopUtil;
|
import com.alttd.playershops.utils.ShopUtil;
|
||||||
import com.alttd.playershops.utils.Util;
|
import com.alttd.playershops.utils.Util;
|
||||||
|
|
@ -13,78 +12,26 @@ import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@DefaultQualifier(NonNull.class)
|
@DefaultQualifier(NonNull.class)
|
||||||
public class CheckStockCommand implements Subcommand {
|
public class CheckStockCommand {
|
||||||
|
|
||||||
@Override
|
public static void doStockCheck(final Player player, int radius, int minimumStock) {
|
||||||
public boolean execute(CommandSender sender, String subCommand, String[] args) {
|
List<Stock> stockList = checkStock(player.getLocation().getBlockX(), player.getLocation().getBlockZ(), radius, player, minimumStock);
|
||||||
return this.doStockCheck(sender, args);
|
sendStockMessage(player, stockList, minimumStock);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
|
|
||||||
// TODO give some default tab completions
|
|
||||||
if (args.length == 1) {
|
|
||||||
return PlayerShopCommands.getListMatchingLast(sender, args, PlayerShopCommand.BASE_PERM + ".checkstock", "help");
|
|
||||||
} else if (args.length == 2) {
|
|
||||||
// return PlayerShopCommands.getListMatchingLast(sender, args, "radius");
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int minimumStock = -1;
|
|
||||||
|
|
||||||
public boolean doStockCheck(final CommandSender sender, final String[] args) {
|
|
||||||
if (!(sender instanceof Player player)) {
|
|
||||||
sender.sendRichMessage("<red>Only players can use this command.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (args.length != 1 && args.length != 2) {
|
|
||||||
player.sendRichMessage("<red>Invalid command syntax, use /checkstock <radius> [minimum stock]");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int radius;
|
|
||||||
try {
|
|
||||||
radius = Integer.parseInt(args[0]);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
player.sendRichMessage("<red>radius has to be a valid number, use /checkstock <radius> [minimum stock]");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (radius > 100 || radius <= 0) {
|
|
||||||
player.sendRichMessage("<red>Please keep the radius between 1 and 100");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length == 2) {
|
|
||||||
try {
|
|
||||||
minimumStock = Integer.parseInt(args[1]);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
player.sendRichMessage("<red>minimum stock has to be a valid number, use /checkstock <radius> [minimum stock]");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List<Stock> stockList = checkStock(player.getLocation().getBlockX(), player.getLocation().getBlockZ(), radius, player);
|
|
||||||
sendStockMessage(player, stockList);
|
|
||||||
highlightLowStock(player, stockList);
|
highlightLowStock(player, stockList);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Stole this code from AlttdUtility by ___Kappa___ and reworked it slightly
|
//Stole this code from AlttdUtility by ___Kappa___ and reworked it slightly
|
||||||
private void highlightLowStock(Player player, List<Stock> stockList) {
|
private static void highlightLowStock(Player player, List<Stock> stockList) {
|
||||||
ParticleBuilder particleBuilder = new ParticleBuilder(Particle.DUST);
|
ParticleBuilder particleBuilder = new ParticleBuilder(Particle.DUST);
|
||||||
particleBuilder.color(255, 255, 255);
|
particleBuilder.color(255, 255, 255);
|
||||||
particleBuilder.receivers(player);
|
particleBuilder.receivers(player);
|
||||||
|
|
@ -139,7 +86,7 @@ public class CheckStockCommand implements Subcommand {
|
||||||
* @param caller Player who is checking for stock, can only see the stock from their shops unless they have base_perm.checkstock.bypass
|
* @param caller Player who is checking for stock, can only see the stock from their shops unless they have base_perm.checkstock.bypass
|
||||||
* @return A list of Stock that the player is allowed to see
|
* @return A list of Stock that the player is allowed to see
|
||||||
*/
|
*/
|
||||||
private List<Stock> checkStock(int x, int z, int radius, Player caller) {
|
private static List<Stock> checkStock(int x, int z, int radius, Player caller, int minimumStock) {
|
||||||
List<PlayerShop> shops = PlayerShops.getInstance().getShopHandler().getShopsInRadius(x, z, radius);
|
List<PlayerShop> shops = PlayerShops.getInstance().getShopHandler().getShopsInRadius(x, z, radius);
|
||||||
Stream<PlayerShop> playerShopStream = shops.stream();
|
Stream<PlayerShop> playerShopStream = shops.stream();
|
||||||
if (minimumStock != -1)
|
if (minimumStock != -1)
|
||||||
|
|
@ -157,8 +104,7 @@ public class CheckStockCommand implements Subcommand {
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String putInConfig = "<yellow><click:run_command:'/cmi tppos <x> <y> <z>'>[<aqua><item_component></aqua>] <amount> left in stock</click></yellow>";
|
private static void sendStockMessage(Player player, List<Stock> stockList, int minimumStock) {
|
||||||
private void sendStockMessage(Player player, List<Stock> stockList) {
|
|
||||||
Component component = null;
|
Component component = null;
|
||||||
for (Stock stock : stockList) {
|
for (Stock stock : stockList) {
|
||||||
TagResolver resolver = TagResolver.resolver(
|
TagResolver resolver = TagResolver.resolver(
|
||||||
|
|
@ -169,9 +115,9 @@ public class CheckStockCommand implements Subcommand {
|
||||||
Placeholder.parsed("amount", stock.stock + "")
|
Placeholder.parsed("amount", stock.stock + "")
|
||||||
);
|
);
|
||||||
if (component == null)
|
if (component == null)
|
||||||
component = Util.parseMiniMessage(putInConfig, resolver);
|
component = Util.parseMiniMessage(MessageConfig.SHOP_STOCK_CHECK, resolver);
|
||||||
else
|
else
|
||||||
component = component.append(Component.newline()).append(Util.parseMiniMessage(putInConfig, resolver));
|
component = component.append(Component.newline()).append(Util.parseMiniMessage(MessageConfig.SHOP_STOCK_CHECK, resolver));
|
||||||
}
|
}
|
||||||
if (component == null)
|
if (component == null)
|
||||||
if (minimumStock == -1)
|
if (minimumStock == -1)
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
package com.alttd.playershops.commands.subcommands;
|
|
||||||
|
|
||||||
import com.alttd.playershops.PlayerShops;
|
|
||||||
import com.alttd.playershops.commands.Subcommand;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
|
||||||
|
|
||||||
@DefaultQualifier(NonNull.class)
|
|
||||||
public class ReloadCommand implements Subcommand {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
|
|
||||||
PlayerShops.getInstance().reloadConfigs();
|
|
||||||
// Todo message when config is reloaded
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
package com.alttd.playershops.commands.subcommands;
|
|
||||||
|
|
||||||
import com.alttd.playershops.PlayerShops;
|
|
||||||
import com.alttd.playershops.commands.Subcommand;
|
|
||||||
import com.alttd.playershops.shop.PlayerShop;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@DefaultQualifier(NonNull.class)
|
|
||||||
public class TransferShopsCommand implements Subcommand {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean execute(CommandSender sender, String subCommand, String[] args) {
|
|
||||||
if (!(sender instanceof Player player)) {
|
|
||||||
sender.sendRichMessage("<red>Only players can use this command.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (args.length != 1 && args.length != 2) {
|
|
||||||
player.sendRichMessage("<red>Invalid command syntax, use /transfershops <uuid> <newplayer>");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
OfflinePlayer oldOfflinePlayer = Bukkit.getOfflinePlayer(args[0]);
|
|
||||||
if (!oldOfflinePlayer.hasPlayedBefore()) {
|
|
||||||
player.sendRichMessage("<red>" + args[0] + " has not joined this server before.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Player newShopOwner = Bukkit.getPlayer(args[1]);
|
|
||||||
if (newShopOwner == null) {
|
|
||||||
player.sendRichMessage("<red>" + args[1] + " is not online and has to be online for this process.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
UUID oldUUID = oldOfflinePlayer.getUniqueId();
|
|
||||||
List<PlayerShop> playerShops = PlayerShops.getInstance().getShopHandler().getShops(oldUUID);
|
|
||||||
sender.sendRichMessage("<red>Starting the transfer process now, this might lag the server.");
|
|
||||||
for (PlayerShop playerShop : playerShops) {
|
|
||||||
playerShop.setOwner(newShopOwner);
|
|
||||||
}
|
|
||||||
newShopOwner.sendRichMessage(playerShops.size() + " have been transferred to you.");
|
|
||||||
sender.sendRichMessage(playerShops.size() + " have been transferred to " + args[1] + ".");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -143,9 +143,11 @@ public class MessageConfig {
|
||||||
|
|
||||||
public static String SHOP_INFO = "<yellow>This shop <action> <gold><amount></gold> <item> for <gold><price></gold>.</yellow>";
|
public static String SHOP_INFO = "<yellow>This shop <action> <gold><amount></gold> <item> for <gold><price></gold>.</yellow>";
|
||||||
public static String SHOP_STOCK_INFO = "<yellow>This <type> shop has <gold><stock></gold> stock.</yellow>";
|
public static String SHOP_STOCK_INFO = "<yellow>This <type> shop has <gold><stock></gold> stock.</yellow>";
|
||||||
|
public static String SHOP_STOCK_CHECK = "<yellow><click:run_command:'/cmi tppos <x> <y> <z>'>[<aqua><item_component></aqua>] <amount> left in stock</click></yellow>";
|
||||||
private static void otherMessages() {
|
private static void otherMessages() {
|
||||||
SHOP_INFO = getString("messages.shop-info", SHOP_INFO);
|
SHOP_INFO = getString("messages.shop-info", SHOP_INFO);
|
||||||
SHOP_STOCK_INFO = getString("messages.shop-stock-info", SHOP_STOCK_INFO);
|
SHOP_STOCK_INFO = getString("messages.shop-stock-info", SHOP_STOCK_INFO);
|
||||||
|
SHOP_STOCK_CHECK = getString("messages.shop-stock-check", SHOP_STOCK_CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String CHANGE_PRICE_PROMPT = "What should the price be? Type cancel to cancel this action.";
|
public static String CHANGE_PRICE_PROMPT = "What should the price be? Type cancel to cancel this action.";
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,11 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.block.DoubleChest;
|
import org.bukkit.block.DoubleChest;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.InventoryHolder;
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
|
||||||
|
|
@ -178,4 +180,25 @@ public class ShopHandler {
|
||||||
return playerSettings.computeIfAbsent(uuid, PlayerSettings::loadFromFile);
|
return playerSettings.computeIfAbsent(uuid, PlayerSettings::loadFromFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void transferShops(CommandSender sender, OfflinePlayer oldOwner, OfflinePlayer newOwner) {
|
||||||
|
if (!oldOwner.hasPlayedBefore()) {
|
||||||
|
sender.sendRichMessage("<red>" + oldOwner.getName() + " has not joined this server before.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newOwner.hasPlayedBefore()) {
|
||||||
|
sender.sendRichMessage("<red>" + newOwner.getName() + " has not joined this server before.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PlayerShop> playerShops = PlayerShops.getInstance().getShopHandler().getShops(oldOwner.getUniqueId());
|
||||||
|
sender.sendRichMessage("<red>Starting the transfer process now, this might lag the server.");
|
||||||
|
for (PlayerShop playerShop : playerShops) {
|
||||||
|
playerShop.setOwner(newOwner);
|
||||||
|
}
|
||||||
|
if (newOwner.isOnline() && newOwner.getPlayer() != null) {
|
||||||
|
newOwner.getPlayer().sendRichMessage(playerShops.size() + " have been transferred to you.");
|
||||||
|
}
|
||||||
|
sender.sendRichMessage(playerShops.size() + " from " + oldOwner.getName() + " have been transferred to " + newOwner.getName() + ".");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.block.Sign;
|
import org.bukkit.block.Sign;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
|
|
@ -134,7 +135,7 @@ public class PlayerShop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOwner(Player player) {
|
public void setOwner(OfflinePlayer player) {
|
||||||
ownerUUID = player.getUniqueId();
|
ownerUUID = player.getUniqueId();
|
||||||
ownerName = player.getName();
|
ownerName = player.getName();
|
||||||
update();
|
update();
|
||||||
|
|
|
||||||
5
src/main/java/com/alttd/playershops/utils/Pair.java
Normal file
5
src/main/java/com/alttd/playershops/utils/Pair.java
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.alttd.playershops.utils;
|
||||||
|
|
||||||
|
public record Pair<X, Y>(X x, Y y) {
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user