Skip to content

Commit

Permalink
Merge branch 'dev/chatpreview' into dev/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
JorelAli committed Jul 21, 2022
2 parents 3175961 + 990dc68 commit c3337c6
Show file tree
Hide file tree
Showing 12 changed files with 317 additions and 10 deletions.
12 changes: 12 additions & 0 deletions commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;

Expand Down Expand Up @@ -103,6 +104,7 @@ public static void onDisable() {
CommandAPI.config = null;
CommandAPI.logger = null;
CommandAPI.loaded = false;

CommandAPIHandler.onDisable();
}

Expand Down Expand Up @@ -201,6 +203,16 @@ public static void onEnable(Plugin plugin) {
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent e) {
CommandAPIHandler.getInstance().getNMS().resendPackets(e.getPlayer());
if(Bukkit.shouldSendChatPreviews()) {
CommandAPIHandler.getInstance().getNMS().hookChatPreview(plugin, e.getPlayer());
}
}

@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
if(Bukkit.shouldSendChatPreviews()) {
CommandAPIHandler.getInstance().getNMS().unhookChatPreview(e.getPlayer());
}
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.bukkit.ChatColor;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.help.HelpTopic;
import org.bukkit.permissions.Permission;

Expand All @@ -63,10 +64,14 @@
import dev.jorel.commandapi.arguments.Argument;
import dev.jorel.commandapi.arguments.ArgumentSuggestions;
import dev.jorel.commandapi.arguments.ICustomProvidedArgument;
import dev.jorel.commandapi.arguments.IPreviewable;
import dev.jorel.commandapi.arguments.LiteralArgument;
import dev.jorel.commandapi.arguments.MultiLiteralArgument;
import dev.jorel.commandapi.arguments.PreviewInfo;
import dev.jorel.commandapi.nms.NMS;
import dev.jorel.commandapi.preprocessor.RequireField;
import dev.jorel.commandapi.wrappers.Preview;
import net.kyori.adventure.text.Component;

/**
* Handles the main backend of the CommandAPI. This constructs brigadier Command
Expand Down Expand Up @@ -143,6 +148,12 @@ public static CommandAPIHandler<?> getInstance() {
}

static void onDisable() {
if(instance != null) {
for(Player player : Bukkit.getOnlinePlayers()) {
instance.NMS.unhookChatPreview(player);
}
}

instance = null;
}

Expand All @@ -151,6 +162,7 @@ static void onDisable() {
final NMS<CommandSourceStack> NMS;
final CommandDispatcher<CommandSourceStack> DISPATCHER;
final List<RegisteredCommand> registeredCommands; // Keep track of what has been registered for type checking
final Map<List<String>, Optional<Preview>> previewableArguments; // Arguments with previewable chat
private PaperImplementations paper;

@SuppressWarnings("unchecked")
Expand All @@ -164,6 +176,7 @@ private CommandAPIHandler() {
}
DISPATCHER = NMS.getBrigadierDispatcher();
registeredCommands = new ArrayList<>();
previewableArguments = new HashMap<>();
this.paper = new PaperImplementations(false, NMS);
}

Expand Down Expand Up @@ -670,6 +683,24 @@ void register(CommandMetaData meta, final Argument<?>[] args,
}
registeredCommands.add(new RegisteredCommand(commandName, argumentsString, shortDescription, fullDescription, aliases, permission));
}

// Handle previewable arguments
if(args.length > 0 && args[args.length - 1] instanceof IPreviewable<?> previewable) {
List<String> path = new ArrayList<>();

path.add(commandName);
for(Argument<?> arg : args) {
path.add(arg.getNodeName());
}
previewableArguments.put(List.copyOf(path), previewable.getPreview());

// And aliases
for(String alias : aliases) {
path.remove(0);
path.add(alias);
previewableArguments.put(List.copyOf(path), previewable.getPreview());
}
}

if (Bukkit.getPluginCommand(commandName) != null) {
CommandAPI.logWarning("Plugin command /" + commandName + " is registered by Bukkit ("
Expand Down Expand Up @@ -872,6 +903,22 @@ SuggestionProvider<CommandSourceStack> toSuggestions(String nodeName, Argument<?
return suggestionsToAddOrOverride.orElse(ArgumentSuggestions.empty()).suggest(suggestionInfo, builder);
};
}

/**
* Looks up the function to generate a chat preview for a path of nodes in the
* command tree. This is a method internal to the CommandAPI and isn't expected
* to be used by plugin developers (but you're more than welcome to use it as
* you see fit).
*
* @param path a list of Strings representing the path (names of command nodes)
* to (and including) the previewable argument
* @return a function that takes in a {@link PreviewInfo} and returns a
* {@link Component}. If such a function is not available, this will
* return a function that always returns null.
*/
public Preview lookupPreviewable(List<String> path) {
return previewableArguments.getOrDefault(path, Optional.empty()).orElseGet(() -> info -> null);
}

/////////////////////////
// SECTION: Reflection //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,29 @@
*******************************************************************************/
package dev.jorel.commandapi.arguments;

import java.util.Optional;

import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;

import dev.jorel.commandapi.CommandAPIHandler;
import dev.jorel.commandapi.exceptions.PaperAdventureNotFoundException;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.nms.NMS;
import dev.jorel.commandapi.wrappers.Preview;
import net.kyori.adventure.text.Component;

/**
* An argument that represents chat with entity selectors
*
* @apiNote Returns a {@link Component} object
*/
public class AdventureChatArgument extends Argument<Component> implements IGreedyArgument {
public class AdventureChatArgument extends Argument<Component> implements IGreedyArgument, IPreviewable<AdventureChatArgument> {

private Preview preview;

/**
* Constructs a Chat argument with a given node name. Represents fancy greedy
Expand All @@ -42,10 +52,10 @@ public class AdventureChatArgument extends Argument<Component> implements IGreed
*/
public AdventureChatArgument(String nodeName) {
super(nodeName, CommandAPIHandler.getInstance().getNMS()._ArgumentChat());

try {
Class.forName("net.kyori.adventure.text.Component");
} catch(ClassNotFoundException e) {
} catch (ClassNotFoundException e) {
throw new PaperAdventureNotFoundException(this.getClass());
}
}
Expand All @@ -54,15 +64,34 @@ public AdventureChatArgument(String nodeName) {
public Class<Component> getPrimitiveType() {
return Component.class;
}

@Override
public CommandAPIArgumentType getArgumentType() {
return CommandAPIArgumentType.ADVENTURE_CHAT;
}

@Override
public <CommandListenerWrapper> Component parseArgument(NMS<CommandListenerWrapper> nms,
CommandContext<CommandListenerWrapper> cmdCtx, String key, Object[] previousArgs) throws CommandSyntaxException {
CommandContext<CommandListenerWrapper> cmdCtx, String key, Object[] previousArgs) throws CommandSyntaxException {
final CommandSender sender = nms.getCommandSenderFromCSS(cmdCtx.getSource());
if(getPreview().isPresent() && sender instanceof Player player) {
try {
getPreview().get().generatePreview(new PreviewInfo(player, CommandAPIHandler.getRawArgumentInput(cmdCtx, key), cmdCtx.getInput()));
} catch (WrapperCommandSyntaxException e) {
throw e.getException();
}
}
return nms.getAdventureChat(cmdCtx, key);
}

@Override
public AdventureChatArgument withPreview(Preview preview) {
this.preview = preview;
return this;
}

@Override
public Optional<Preview> getPreview() {
return Optional.ofNullable(preview);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,30 @@
*******************************************************************************/
package dev.jorel.commandapi.arguments;

import java.util.Optional;

import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;

import dev.jorel.commandapi.CommandAPIHandler;
import dev.jorel.commandapi.exceptions.SpigotNotFoundException;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.nms.NMS;
import dev.jorel.commandapi.wrappers.Preview;
import net.md_5.bungee.api.chat.BaseComponent;

/**
* An argument that represents chat with entity selectors
*
* @apiNote Returns a {@link BaseComponent}{@code []} object
*/
public class ChatArgument extends Argument<BaseComponent[]> implements IGreedyArgument {
public class ChatArgument extends Argument<BaseComponent[]> implements IGreedyArgument, IPreviewable<ChatArgument> {

private Preview preview;

/**
* Constructs a Chat argument with a given node name. Represents fancy greedy
* strings that can parse entity selectors
Expand Down Expand Up @@ -64,6 +73,25 @@ public CommandAPIArgumentType getArgumentType() {
@Override
public <CommandListenerWrapper> BaseComponent[] parseArgument(NMS<CommandListenerWrapper> nms,
CommandContext<CommandListenerWrapper> cmdCtx, String key, Object[] previousArgs) throws CommandSyntaxException {
final CommandSender sender = nms.getCommandSenderFromCSS(cmdCtx.getSource());
if(getPreview().isPresent() && sender instanceof Player player) {
try {
getPreview().get().generatePreview(new PreviewInfo(player, CommandAPIHandler.getRawArgumentInput(cmdCtx, key), cmdCtx.getInput()));
} catch (WrapperCommandSyntaxException e) {
throw e.getException();
}
}
return nms.getChat(cmdCtx, key);
}

@Override
public ChatArgument withPreview(Preview preview) {
this.preview = preview;
return this;
}

@Override
public Optional<Preview> getPreview() {
return Optional.ofNullable(preview);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package dev.jorel.commandapi.arguments;

import java.util.Optional;

import dev.jorel.commandapi.wrappers.Preview;

/**
* An interface representing that the argument can be previewed using
* Minecraft's chat preview feature. To use this, the server must have
* {@code previews-chat=true} set in its {@code server.properties} file
*/
public interface IPreviewable<T extends Argument<?>> {

public T withPreview(Preview preview);

public Optional<Preview> getPreview();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.jorel.commandapi.arguments;

import org.bukkit.entity.Player;

public record PreviewInfo(
/** @param player - the Player typing this command */
Player player,

/**
* @param input - the current partially typed argument. For example "/mycmd tes"
* will return "tes"
*/
String input,

/**
* @param fullInput - a string representing the full current input (including /)
*/
String fullInput) {

}
15 changes: 15 additions & 0 deletions commandapi-core/src/main/java/dev/jorel/commandapi/nms/NMS.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
import org.bukkit.loot.LootTable;
import org.bukkit.plugin.Plugin;
import org.bukkit.potion.PotionEffectType;

import com.mojang.brigadier.CommandDispatcher;
Expand Down Expand Up @@ -344,6 +345,20 @@ String getScoreHolderSingle(CommandContext<CommandListenerWrapper> cmdCtx, Strin
UUID getUUID(CommandContext<CommandListenerWrapper> cmdCtx, String key);

World getWorldForCSS(CommandListenerWrapper clw);

/**
* Hooks into the chat previewing system for 1.19+
* @param plugin the plugin (for async calls)
* @param player the player to hook
*/
default void hookChatPreview(Plugin plugin, Player player) {};

/**
* Unhooks a player from the chat previewing system for 1.19+. This should
* be called when the player quits and when the plugin is disabled
* @param player the player to unhook
*/
default void unhookChatPreview(Player player) {};

/**
* Checks if a Command is an instance of the OBC VanillaCommandWrapper
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package dev.jorel.commandapi.wrappers;

import dev.jorel.commandapi.arguments.PreviewInfo;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import net.kyori.adventure.text.Component;

@FunctionalInterface
public interface Preview {

public Component generatePreview(PreviewInfo info) throws WrapperCommandSyntaxException;

}
Loading

0 comments on commit c3337c6

Please sign in to comment.