Skip to content

Text processing

Text processors are the foundation of the API. We include a default GlobalTextProcessor which can be accessed with Social.get().getTextProcessor(). The global text processor stores text parsers and provides a few utilities.

Processing a message

Processing a message with social's registered parsers is possible via the GlobalTextProcessor::parse method. You'll have to provide a parser context. This is easier than it sounds:

Note

This part of the guide assumes you already know how to get a SocialUser instance.

// Let's start by building a context
var context = SocialParserContext.builder(user, Component.text("Hello, $(nickname)! :smile:"))
    .build();

// Now we can proceed to parse the message
Component message = Social.get().getTextProcessor().parse(context);

Alternative methods

The global text processor provides some alternative methods so that you don't have to build a new context every time. This can be especially useful when you have to parse many messages:

  • parse(user, channel, message): parses a message and returns a Component
    • user must be an instance of SocialUser
    • channel must be an instance of ChatChannel
    • message can be a Component or a String
  • parseAndSend(user, channel, message): parses and sends a message to the user
    • user must be an instance of SocialUser
    • channel must be an instance of ChatChannel
    • message can be a Component or a String

Registering custom placeholders

You can register placeholders in the global text processor by extending the SocialContextualPlaceholder class or directly using lambda expressions. In this example we'll focus on the latter:

var identifier = "example_placeholder"; // Our placeholder will be $(example_placeholder)

Social.get().getTextProcessor().registerContextualPlaceholder(identifier, context -> { 
    // Context is a SocialParserContext
    return Component.text(context.user().displayName().color(NamedTextColor.GOLD));
});

This placeholder will return the player's display name in gold color.

Registering custom keywords

The process of registering keywords is the same as in the previous example but using the method GlobalTextProcessor::registerContextualKeyword:

var keyword = "example_keyword"; // Our keyword will be [example_keyword]

Social.get().getTextProcessor().registerContextualKeyword(keyword, context -> {
    return Component.text("Click me!")
        .clickEvent(ClickEvent.runCommand("/me hello world!"));
});

Tip

Don't forget that keywords are used by players. Make them simple and intuitive, but also fun!

Registering custom formatters

Formatters are a new feature that allow users to add a personal touch to their messages. There are two types of formatters:

  • Inline formatters: they require the user to put a prefix in their messages. They can be delimited by using the '\' key.
  • Surrounding formatters: they require the user to "surround" their message in a special character.

Formatters are considered an experimental feature right now, so using them requires to extend the SocialInlineFormatter or SocialSurroundingFormatter class:

ExampleFormatter.java
public class ExampleFormatter extends SocialSurroundingFormatter {

    @Override
    public String characters() {
        return "$$";
    }

    @Override
    public Component format(SocialParserContext context) {
        return context.message().font(Key.key("custom:font"));
    }

}

Note

This example changes the font of the surrounded text, for example: $$Hello!$$ How are you?.

The last step is registering this parser:

Social.get().getTextProcessor().registerContextualParser(new ExampleFormatter());

Registering custom parsers

Parsers allow a deeper level of integration but come at the cost of more effort required from the developer. Let's start by implementing the SocialContextualParser interface:

ExampleParser.java
public class ExampleParser implements SocialContextualParser {

    @Override
    public Component parse(SocialParserContext context) {
        return context.message().replaceText(TextReplacementConfig.builder()
            .matchLiteral("try the ketchup")
            .replacement(Component.text("try the ketchup").color(NamedTextColor.RED))
            .build())
    }

}

Customizing parsers

You can configure your parser by implementing additional interfaces. By default, parsers will work with non-player input. To change this you can implement the interface SocialUserInputParser, which will make the parser work both with player and non-player input. If you want your parser to work only with player input, you can implement SocialFilterLike instead of SocialUserInputParser.

Version 0.4 introduces an experimental method to make your parser work with offline players or in instances where you won't need to access the context's user in any way. This can be done by overriding supportsOfflinePlayers():

ExampleParser.java
    @Override
    public boolean supportsOfflinePlayers() {
        return true;
    }

Other registration methods

The global text processor has public static variables for two specific parser groups: early and late parsers. Generally, we recommend using the built-in methods to register parsers, but we do understand and support the fact that there are a lot of use cases for parsers which may not align with the ideas we envisioned for the API.

  • Early parsers: they are parsed before registered parsers
  • Late parsers: they are parsed after registered parsers

Let's register our ExampleParser as a late parser:

Registering early/late parsers
Social.get().getTextProcessor().LATE_PARSERS.add(new ExampleParser());