001/* 002 * Copyright 2021 Siroshun09 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.github.siroshun09.mccommand.paper; 018 019import com.github.siroshun09.mccommand.common.Command; 020import com.github.siroshun09.mccommand.common.context.CommandContext; 021import com.github.siroshun09.mccommand.common.context.SimpleCommandContext; 022import com.github.siroshun09.mccommand.paper.sender.PaperSender; 023import org.bukkit.command.CommandExecutor; 024import org.bukkit.command.CommandSender; 025import org.bukkit.command.PluginCommand; 026import org.bukkit.command.TabCompleter; 027import org.bukkit.plugin.Plugin; 028import org.bukkit.plugin.java.JavaPlugin; 029import org.jetbrains.annotations.NotNull; 030import org.jetbrains.annotations.Nullable; 031 032import java.util.List; 033import java.util.concurrent.Executor; 034import java.util.concurrent.Executors; 035 036public final class PaperCommandFactory { 037 038 private PaperCommandFactory() { 039 throw new UnsupportedOperationException(); 040 } 041 042 /** 043 * Registers the command. 044 * 045 * @param target the {@link PluginCommand} 046 * @param command the command to register 047 */ 048 public static void register(@NotNull PluginCommand target, @NotNull Command command) { 049 PaperCommandImpl paperCommand = new PaperCommandImpl(command); 050 051 target.setExecutor(paperCommand); 052 target.setTabCompleter(paperCommand); 053 } 054 055 /** 056 * Searches for {@link PluginCommand} that is named as {@link Command#getName()} 057 * and register the command if it exists. 058 * 059 * @param sourcePlugin the plugin to search for the command 060 * @param command the command to register 061 */ 062 public static void registerIfExists(@NotNull JavaPlugin sourcePlugin, @NotNull Command command) { 063 PluginCommand pluginCommand = sourcePlugin.getCommand(command.getName()); 064 065 if (pluginCommand != null) { 066 register(pluginCommand, command); 067 } 068 } 069 070 /** 071 * Registers the command. 072 * <p> 073 * If you register a command with this method, it will be executed asynchronously. 074 * <p> 075 * Note: 076 * <p> 077 * The tab completion will execute on main thread. 078 * <p> 079 * If you want the tab completion to be executed asynchronously, use 080 * {@link com.github.siroshun09.mccommand.paper.listener.AsyncTabCompleteListener#register(Plugin, Command)}. 081 * 082 * @param target the {@link PluginCommand} 083 * @param command the command to register 084 */ 085 public static void registerAsync(@NotNull PluginCommand target, @NotNull Command command) { 086 registerAsync(target, command, Executors.newSingleThreadExecutor()); 087 } 088 089 /** 090 * Searches for {@link PluginCommand} that is named as {@link Command#getName()} 091 * and register the command if it exists. 092 * 093 * @param sourcePlugin the plugin to search for the command 094 * @param command the command to register 095 * @see PaperCommandFactory#registerAsync(PluginCommand, Command) 096 */ 097 public static void registerAsyncIfExists(@NotNull JavaPlugin sourcePlugin, @NotNull Command command) { 098 PluginCommand pluginCommand = sourcePlugin.getCommand(command.getName()); 099 100 if (pluginCommand != null) { 101 registerAsync(pluginCommand, command); 102 } 103 } 104 105 /** 106 * Registers the command. 107 * <p> 108 * If you register a command with this method, it will be executed asynchronously. 109 * <p> 110 * Note: 111 * <p> 112 * The tab completion will execute on main thread. 113 * <p> 114 * If you want the tab completion to be executed asynchronously, use {@link com.github.siroshun09.mccommand.paper.listener.AsyncTabCompleteListener#register(Plugin, Command)}. 115 * 116 * @param target the {@link PluginCommand} 117 * @param command the command to register 118 * @param executor the executor to run command 119 */ 120 public static void registerAsync(@NotNull PluginCommand target, @NotNull Command command, @NotNull Executor executor) { 121 AsyncPaperCommandImpl paperCommand = new AsyncPaperCommandImpl(command, executor); 122 123 target.setExecutor(paperCommand); 124 target.setTabCompleter(paperCommand); 125 } 126 127 /** 128 * Searches for {@link PluginCommand} that is named as {@link Command#getName()} 129 * and register the command if it exists. 130 * 131 * @param sourcePlugin the plugin to search for the command 132 * @param command the command to register 133 * @param executor the executor to run command 134 * @see PaperCommandFactory#registerAsync(PluginCommand, Command) 135 */ 136 public static void registerAsyncIfExists(@NotNull JavaPlugin sourcePlugin, @NotNull Command command, 137 @NotNull Executor executor) { 138 PluginCommand pluginCommand = sourcePlugin.getCommand(command.getName()); 139 140 if (pluginCommand != null) { 141 registerAsync(pluginCommand, command, executor); 142 } 143 } 144 145 private static class PaperCommandImpl implements CommandExecutor, TabCompleter { 146 147 private final Command command; 148 149 private PaperCommandImpl(@NotNull Command command) { 150 this.command = command; 151 } 152 153 @Override 154 public boolean onCommand(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command cmd, 155 @NotNull String label, @NotNull String[] args) { 156 command.onExecution( 157 createContext(sender, label, args) 158 ); 159 160 return true; 161 } 162 163 @Override 164 public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command cmd, 165 @NotNull String label, @NotNull String[] args) { 166 return command.onTabCompletion( 167 createContext(sender, label, args) 168 ); 169 } 170 171 private CommandContext createContext(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { 172 return SimpleCommandContext.newBuilder() 173 .setCommand(command) 174 .setSender(new PaperSender(sender)) 175 .setArguments(args) 176 .setLabel(label) 177 .build(); 178 } 179 } 180 181 private static class AsyncPaperCommandImpl implements CommandExecutor, TabCompleter { 182 183 private final Command command; 184 private final Executor executor; 185 186 private AsyncPaperCommandImpl(@NotNull Command command, @NotNull Executor executor) { 187 this.command = command; 188 this.executor = executor; 189 } 190 191 @Override 192 public boolean onCommand(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command cmd, 193 @NotNull String label, @NotNull String[] args) { 194 executor.execute(() -> 195 command.onExecution( 196 createContext(sender, label, args) 197 )); 198 199 return true; 200 } 201 202 @Override 203 public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command cmd, 204 @NotNull String label, @NotNull String[] args) { 205 return command.onTabCompletion( 206 createContext(sender, label, args) 207 ); 208 } 209 210 private CommandContext createContext(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { 211 return SimpleCommandContext.newBuilder() 212 .setCommand(command) 213 .setSender(new PaperSender(sender)) 214 .setArguments(args) 215 .setLabel(label) 216 .build(); 217 } 218 } 219}