1. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Копирование текста в буфер обмена

Тема в разделе "Разработка плагинов для новичков", создана пользователем Korvinius, 27 ноя 2022.

  1. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    сделал пока так, надеюсь сработает:
    PHP:
                if (isClassPresent("net.kyori.adventure.text.Component") && isClassPresent("net.kyori.adventure.platform.bukkit.BukkitAudiences")) {
                    
    BukkitAudiences adventure BukkitAudiences.create(plugin);
                    
    Component message Component.text(TextDecoration.UNDERLINED "Click to copy")
                            .
    hoverEvent(net.kyori.adventure.text.event.HoverEvent.showText(Component.text("Private text")))
                            .
    clickEvent(net.kyori.adventure.text.event.ClickEvent.copyToClipboard("Private text"));
                    
    adventure.sender(sender).sendMessage(message);
                    return 
    true;
                }else if (
    isClassPresent("net.md_5.bungee.api.chat.BaseComponent")) {
                    
    TextComponent message = new TextComponent(TextDecoration.UNDERLINED "Click to copy");
                    
    message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Private text")));
                    
    message.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD"Private text"));
                    
    sender.spigot().sendMessage(message);
                    return 
    true;
                }else {
                    
    sender.sendMessage("Private text");
                    return 
    true;
                }
     
  2. Dymeth

    Dymeth Активный участник Пользователь

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    sendMessage() - это метод с кучей перегрузок. Так, например, в Paper класс CommandSender реализует интерфейс Audience. И в этом методе метод sendMessage() прекрасно принимает Component:
    upload_2022-12-7_21-8-7.png
    Так что всё будет работать.
    Да и если бы оно не работало - ты бы узнал об этом от IDE, тебе бы просто не дало скомпилировать код, в котором ты передаёшь параметры неверного типа в метод.

    Ты моешь прям в IDE посмотреть, какие есть варианты использования .sendMessage():
    upload_2022-12-7_21-9-4.png
     
  3. Dymeth

    Dymeth Активный участник Пользователь

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    На всякий случай протестируй работу и на Paper, и на Spigot. Убедись, что выполняются корректные ветви условий. Потом можешь сделать отдельный метод для отправки сообщений и использовать его везде в своём плагине. Единственное - я бы рекомендовал закэшировать результат isClassPresent(), чтобы не генерировать новых исключений каждый раз при отправке сообщений
     
  4. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    на Spigot исключение:
    Код:
    [16:03:43] [Server thread/ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'anh' in plugin AnhMine v0.0.1
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:47) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at org.bukkit.craftbukkit.v1_17_R1.CraftServer.dispatchCommand(CraftServer.java:790) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.server.network.PlayerConnection.handleCommand(PlayerConnection.java:1931) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1770) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1751) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:46) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.network.protocol.game.PacketPlayInChat.a(PacketPlayInChat.java:1) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.network.protocol.PlayerConnectionUtils.lambda$0(PlayerConnectionUtils.java:30) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.server.TickTask.run(SourceFile:18) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.util.thread.IAsyncTaskHandler.executeTask(SourceFile:151) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.util.thread.IAsyncTaskHandlerReentrant.executeTask(SourceFile:23) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.util.thread.IAsyncTaskHandler.executeNext(SourceFile:125) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.server.MinecraftServer.bf(MinecraftServer.java:1148) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.server.MinecraftServer.executeNext(MinecraftServer.java:1141) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.util.thread.IAsyncTaskHandler.awaitTasks(SourceFile:134) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.server.MinecraftServer.sleepForTick(MinecraftServer.java:1125) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.server.MinecraftServer.x(MinecraftServer.java:1054) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at net.minecraft.server.MinecraftServer.lambda$0(MinecraftServer.java:305) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at java.lang.Thread.run(Thread.java:833) [?:?]
    Caused by: java.lang.NoClassDefFoundError: net/kyori/adventure/text/Component
            at ink.anh.anhmine.cmd.anh.CmdAnhydrite.onCommand(CmdAnhydrite.java:27) ~[?:?]
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            ... 19 more
    Caused by: java.lang.ClassNotFoundException: net.kyori.adventure.text.Component
            at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:147) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:99) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?]
            at ink.anh.anhmine.cmd.anh.CmdAnhydrite.onCommand(CmdAnhydrite.java:27) ~[?:?]
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[middle171.jar:3284a-Spigot-3892929-0ab8487]
            ... 19 more
    
     
  5. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    Как это сделать?
     
  6. Dymeth

    Dymeth Активный участник Пользователь

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Ну вынести в переменную класса это.
    Для читабельности по желанию можно вообще инициализировать какой-нибудь MessagesFramework и проверять его при отправке сообщения:
    PHP:
    enum MessagesFramework {
        
    PLAIN_TEXT,
        
    ADVENTURE,
        
    MD_5
    }
     
  7. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    Эти исключения возникали ещё на этапе считывания импортов:
    Код:
    import net.kyori.adventure.platform.bukkit.BukkitAudiences;
    import net.kyori.adventure.text.Component;
    Чтобы их избежать вынес все действия в отдельные классы, 1:
    PHP:
    package ink.anh.anhmine.utils.chat;

    import org.bukkit.entity.Player;

    public class 
    MessagePlainText {

        private static 
    boolean allright;
      
        public static 
    boolean message(Player playerString privateMessage) {
            
    player.sendMessage(privateMessage);
            
    allright true;
            return 
    allright;
        }
    }
    2:
    PHP:
    package ink.anh.anhmine.utils.chat;

    import org.bukkit.entity.Player;

    import net.md_5.bungee.api.chat.ClickEvent;
    import net.md_5.bungee.api.chat.HoverEvent;
    import net.md_5.bungee.api.chat.TextComponent;
    import net.md_5.bungee.api.chat.hover.content.Text;

    public class 
    MessageMD_5 {

        private static 
    boolean allright;
      
        public static 
    boolean message(Player playerString hoverMessageString privateMessageString copyText) {
            
    TextComponent message = new TextComponent(hoverMessage);
            
    message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(privateMessage)));
            
    message.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARDcopyText));
            
    player.spigot().sendMessage(message);
            
    allright true;
            return 
    allright;
        }
    }
    3:
    PHP:
    package ink.anh.anhmine.utils.chat;

    import org.bukkit.entity.Player;

    import ink.anh.anhmine.AnhMine;
    import net.kyori.adventure.platform.bukkit.BukkitAudiences;
    import net.kyori.adventure.text.Component;

    public class 
    MessageAdventure {

        private static 
    boolean allright;
      
        public static 
    boolean message(Player playerString hoverMessageString privateMessageString copyText) {
            
    BukkitAudiences adventure BukkitAudiences.create(AnhMine.getInstance());

            
    Component message Component.text(hoverMessage)
                    .
    hoverEvent(net.kyori.adventure.text.event.HoverEvent.showText(Component.text(privateMessage)))
                    .
    clickEvent(net.kyori.adventure.text.event.ClickEvent.copyToClipboard(copyText));
            
    adventure.sender(player).sendMessage(message);
            
    allright true;
            return 
    allright;
        }
    }
    и потому, что в Paper нет класса net.kyori.adventure.platform.bukkit.BukkitAudiences пришлось сделать 4-й:
    PHP:
    package ink.anh.anhmine.utils.chat;

    import org.bukkit.entity.Player;

    import ink.anh.anhmine.AnhMine;
    import net.kyori.adventure.text.Component;

    public class 
    MessagePaper {

        private static 
    boolean allright;
      
        public static 
    boolean message(Player playerString hoverMessageString privateMessageString copyText) {

            
    Component message Component.text(hoverMessage)
                    .
    hoverEvent(net.kyori.adventure.text.event.HoverEvent.showText(Component.text(privateMessage)))
                    .
    clickEvent(net.kyori.adventure.text.event.ClickEvent.copyToClipboard(copyText));
            
    player.sendMessage(message);
            
    allright true;
            return 
    allright;
        }
    }
    Соответственно и это:
    PHP:
    package ink.anh.anhmine.utils.chat;

    public 
    enum MessagesFramework {

        
    PLAIN_TEXT,
        
    ADVENTURE,
        
    PAPER,
        
    MD_5;
      
        public static 
    MessagesFramework getFramework() {
            if (
    isClassPresent("net.kyori.adventure.text.Component") && isClassPresent("net.kyori.adventure.platform.bukkit.BukkitAudiences")) {
                return 
    MessagesFramework.ADVENTURE;
            }else if (
    isClassPresent("net.kyori.adventure.text.Component")) {
                return 
    MessagesFramework.PAPER;
            }else if (
    isClassPresent("net.md_5.bungee.api.chat.BaseComponent")) {
                return 
    MessagesFramework.MD_5;
            }else {
                return 
    MessagesFramework.PLAIN_TEXT;
            }
        }
      
        private static 
    boolean isClassPresent(String className) {
            try {
                Class.
    forName(className);
                return 
    true;
            } catch (
    NoClassDefFoundError ClassNotFoundException e) {
                return 
    false;
            }
        }
    }
    вызываются классы отсюда:

    PHP:
                if (AnhMine.getMessFrame() == MessagesFramework.ADVENTURE) {
                    return 
    MessageAdventure.message(playerhoverMessageprivateMessagecopyText);
                }else if (
    AnhMine.getMessFrame() == MessagesFramework.PAPER) {
                    return 
    MessagePaper.message(playerhoverMessageprivateMessagecopyText);
                }else if (
    AnhMine.getMessFrame() == MessagesFramework.MD_5) {
                    return 
    MessageMD_5.message(playerhoverMessageprivateMessagecopyText);
                }else {
                    return 
    MessagePlainText.message(player,  privateMessage);
                }
    Тестировал на Spigot и Paper. И вот тут мне нужно ещё разобраться как лучше сделать, ведь в Paper вылезло исключение:
    Код:
    java.lang.Error: Unresolved compilation problem:
            The method sendMessage(String) in the type CommandSender is not applicable for the arguments (Component)
    
            at ink.anh.anhmine.utils.chat.MessagePaper.message(MessagePaper.java:17) ~[AnhMine.jar:?]
            at ink.anh.anhmine.cmd.anh.CmdNewWallet.execCmdNewWalletRun(CmdNewWallet.java:141) ~[AnhMine.jar:?]
            at ink.anh.anhmine.cmd.anh.CmdNewWallet.lambda$0(CmdNewWallet.java:56) ~[AnhMine.jar:?]
            at org.bukkit.craftbukkit.v1_17_R1.scheduler.CraftTask.run(CraftTask.java:101) ~[patched_1.17.1.jar:git-Paper-411]                                                                                                                 
            at org.bukkit.craftbukkit.v1_17_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:57) ~[patched_1.17.1.jar:git-Paper-411]                                                                                                       
            at com.destroystokyo.paper.ServerSchedulerReportingWrapper.run(ServerSchedulerReportingWrapper.java:22) ~[patched_1.17.1.jar:git-Paper-411]                                                                                       
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?]
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?]
    
    Нужно узнать способ как отправить sendMessage() игроку с поддержкой Audience?
     
  8. Dymeth

    Dymeth Активный участник Пользователь

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Очень интересно, причем тут вдруг String. По идее нормально должно работать.
    Попробуй явно закастовать CommandSender к Audience и посмотри, какое будет исключение.

    А по поводу импортов - достаточно было просто удалить импорты и указать полные пути до классов прям в коде
     
  9. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    "Закастовал" игрока, заработало на отлично!
    PHP:
            Component message Component.text(hoverMessage)
                    .
    hoverEvent(net.kyori.adventure.text.event.HoverEvent.showText(Component.text(privateMessage)))
                    .
    clickEvent(net.kyori.adventure.text.event.ClickEvent.copyToClipboard(copyText));

            
    Audience audience = (Audienceplayer;
            
    audience.sendMessage(message);
    Спасибо!
     

Поделиться этой страницей