Response handlers

This page explains how to use response handlers, which process the return values of command methods, enabling custom handling of command outputs.

Using the ResponseHandler Interface

The ResponseHandler interface is designed for post-processing command responses within a commands framework. It allows you to define custom logic for handling results returned from command methods. This can be particularly useful for processing or formatting responses before they are sent to the command actor.

Example: Handling Adventure's Component Type

In this example, we will create a ResponseHandler that processes responses of type Component from Adventure. The handler will send the formatted text to the command actor's sender.

Custom Response Handler

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;

public class ComponentResponseHandler implements ResponseHandler<BukkitCommandActor, Component> {

    @Override
    public void handleResponse(Component response, ExecutionContext<BukkitCommandActor> context) {
        // Get the sender from the command context
        var sender = context.actor().sender();

        // Send the Component response to the sender
        sender.sendMessage(response);
    }
}

Registering the Handler

To use the ComponentResponseHandler, you need to register it with your command framework:

Example Command Method

Here’s an example command method that returns an Adventure Component:

In this example:

  • The sendMessage method returns a Component with rich text formatting.

  • The ComponentResponseHandler handles the response by sending it to the command actor’s sender.

Here’s a markdown section to include in the documentation, explaining the ResponseHandler.Factory interface and providing the example for handling Optional<T>:


Dynamic Response Handlers with ResponseHandler.Factory

The ResponseHandler.Factory interface allows for the dynamic creation of ResponseHandler instances based on the response type and function annotations. This feature enables more flexible and complex response handling scenarios by composing handlers for different types, such as Optional<T>, Supplier<T>, and others.

Interface Method

  • @Nullable <T> ResponseHandler<A, T> create(@NotNull Type type, @NotNull AnnotationList annotations, @NotNull Lamp<A> lamp)

    Creates a new ResponseHandler for the given type and list of annotations. If the factory does not handle the input, it may return null.

Example: Handling Optional<T>

Here’s an example of a ResponseHandler.Factory implementation that automatically constructs ResponseHandler instances for Optional<T> where T is any type that has a registered response handler:

Explanation

  • getRawType(type): Retrieves the raw type from the generic Type (stripped from generics). Checks if it's Optional.

  • getFirstGeneric(type, Object.class): Extracts the first generic type argument from Optional<T>.

  • lamp.responseHandler(suppliedType, AnnotationList.empty()): Obtains the appropriate ResponseHandler for the type T.

  • optional.ifPresent(value -> delegate.handleResponse(value, context)): Passes the contained value to the delegate handler if present.

This factory implementation ensures that any Optional<T> response types are handled appropriately by delegating to an existing ResponseHandler for T, allowing for flexible and dynamic response processing.

Registration

Last updated

Was this helpful?