Skip to content

Explaination: MessageSystem

Ture Bentzin edited this page Feb 12, 2023 · 14 revisions

The MessageSystem

The MessageSystem is one of the build-in features delivered by the Core. This System allows you to access a central Database of Messages in various Languages and send them to the Players. You can use the MessageAPI to access the MessageSystem from your Core / API. This MessageAPI allows you to get Access to the MiniMessages that can be displayed to the Player. To learn how to send a Message (classic way - Chat Message) please look at the "Introduction: API" Page.

How does the MessageSystem work?

The MessageSystem is powered by the SQL Database provided by the core. This Database is configured via the database.properties file located in the config folder of your master. The MessageSystem will create some tables in the given Database that are used for the management of replacements, messages, and locales. The primary Table is the "messages" Table that has one entry for every "MessageKey" and "locale" the message entered here will be displayed for the messageKey. The Locale is the Language of the Message, the core has the ability to detect the locale of the players automatically if you use the right MessageReciepents. If a specific Locale or Dialect is not available the System can fall back to the "next best" Language or if that is not available then the System will show the Message in the default "EN_US"

So to sum it up: The MessageSystem works by assigning MessageKeys and Locales to MiniMessages.

What is a MiniMesssage

The System uses the MiniMessage format to color and decorate the messages. If you want more information on how these Messages are formatted, then please look at the MiniMessage Documentation.

Replacers in the MessageSystem

The Core uses a custom System for the replacers that could be divided into two, several systems. The first system uses MiniMessage tags and the other uses patterns.

The System that works with the Tags is controlled exclusively by the Database and is designed for permanent replacements over messages. This could be colors, hovers, and of course your prefix.

The MessageSystem that works with patterns is designed to insert data (like player names or values) within the process of sending a Message. A Pattern is built this way:{n} That means that the following patterns are valid: {0} {1} {3} {20} {305} And the following are not; {-3} {-0} {00} {03} {5,6} {da} {three} The replacers are "in order" which means that they start with 0 and go into positive numbers. If a replacer is not filled, it will be displayed as a pattern to the recipient.

MessageReciepent

The MessageSystem is compatible with multiple platforms, which means that you can't send a Message to a Player or CommandSender directly. To send a Message to something, you need to use a MessageRecipeint. The Paper and VelocityCore provide inbuild MessageReciepents to you.

Alternatively, you can use the getMessage(...) methods to get a Message as an Object. This gives you the opportunity to extract the MiniMessage as is and use it for different purposes than sending via chat. With this, you can display them in a Book or as a Name of an Item. But be aware that if the Message is once sent (or extracted), the language cant be changed. So if you translate an Item Name and the item is given to another player, the Name will not change!

Convert a MiniMessage to a Component using AdventureAPI

The AdventureAPI is a Module provided by the core to handle MiniMessage conversion to Components. Please make sure that your Core is capable of AdventureAPI (which means the Core executes and maintains the AdventureCore).

The following example will show you a conversion of a message with the key "lobby.messages.welcome.1" and the locale "E_US" to a Component:

        Message message = API.get().getMessageApi().getMessage("lobby.welcome.1", "EN_US");
        Component component = AdventureAPI.get().getAdventureTagManager().resolve(message);

This method behaves in a way, that if there is no message for your key and locale, a fallback message will be returned. In the case, you want to use automatic fallback to the best locale available for your searched locale, use the following code (with 1.3 or newer). If you are not aware of the behavior and internal structure of the MessageAPI, is suggest using the "Smart" Option to convert a message to a component!

        Message message = API.get().getMessageApi().getMessageSmart("lobby.welcome.1", "DE_DE");
        Component component = AdventureAPI.get().getAdventureTagManager().resolve(message);

This component can be used now.

How to operate the MessageAPI?

If you are new to MessageSystems or if you are just new to MessageSystems that work the way the MessageAPI works, you should read this carefully! The first thing (and most important) question to ask is: "How to access the MessageAPI". First, you need to make sure that your Core is running (so on Paper for example, you need to make sure the PaperCore Plugin is loaded and enabled). If you are sure the Core is running, you can access the API and use it to access the MessageAPI as a part of it:

MessageApi messageApi = API.get().getMessageApi();

I suggest always "getting" the MessageAPI from scratch and not storing it. This ensures the availability of the API and protects you from corrupted data or unwanted nulls or exceptions.

Before you are able to send Messages (or text in general) to the Player (or similar) you need to make sure your message is present within the MessageSystem in the "default_locale". I would never trust other plugins using the core with the process of registering the messages. You need to keep in mind, that you can register your Messages always as a precaution because the registerMessage method will never override exiting data! So in the case that you depend on a message that is registered by a third-party plugin, you can register the message in your plugin anyways without bad consequences. I suggest always registering all messages used by your plugin within the enable process of it, I would dedicate a simple method to it. So now we are ready to register or message into the message system.

    public final void registerMessages() {
        MessageApi messageApi = API.get().getMessageApi();
        messageApi.registerMessage("here.goes.your.message.key","<red>And here goes <rainbow>your own message</rainbow>!");
        messageApi.registerMessage("here.goes.your.second.key","<blue>You should always register your default <bold>message</bold> in english language!");
    }

You can also use three types of "replacements and replacers" within your messages. Let's take a look at them: (of course you can use all three of them at the same time in the same message)

DBReplacements

This type of replacement is meant for "global" use over the entire network (or parts of it), the database manages them centralized and accessible to every core at all time. If you want to use a replacement like this by default in your plugin, you should always make sure the appropriate entry exists in the database! Because of the centralized nature of these replacements, there is currently no 100% implemented API method for adding/registering a replacer for the DB, but you can use the JDBI API to add your own replacement:

        ReplacementBean bean = new ReplacementBean();
        bean.setTag("teamchat_prefix");
        bean.setValue("<gray>[<green>TeamChat</green>]: ");
        bean.setReplacementType("TEXT_CLOSING");
        API.get().getSQLManager().getJdbi().withExtension(ReplacementDAO.class,extension -> {
            extension.insert(bean);
            return null;
        });

(This example is taken out of the TeamChat Plugin for the Core)

If you want to use this replacement, you should be highly familiar with MiniMessage and the MessageSystem in general. If you want to get familiar with this type of replacement, you may want to take a look at the JDBITagAdapter

Trusted Replacements

Trusted Replacements are way easier to use and are one of two ways to insert data, text, or values into your message specifically for every message you send. That means, that you can influence for every sending process of a message what is inserted into the "placeholders". The Trusted here means, that in this replacer you can use Tags from MiniMessage (like colors or hovers), but this should be used with caution because they should always be compatible and never depend directly on the format or decoration of the default message. You should never use this type of replacer if you enter user-generated content here (like messages), because this input can "bleed" into other parts of your message!!

How to create a "Trusted Replacement? To enable the insertion of content into your message, you need to specify in your default message, that you want reserved space for your replacement. In this case you can do this by adding a "pattern", this is a simple chain of characters, that is recognized by the messageSystem. The pattern for the trusted message looks like this: [0],[1]...[n]. What this means is, that a pattern needs to be a number with a [ in front and a ] behind it. These numbers work like indexes and go from 0 - 2147483647. So a registering process of a message with two trusted replaces could look like this:

            MessageApi messageApi = API.get().getMessageApi();
            messageApi.registerMessage("here.goes.your.message.key","<blue>[0]<blue><green> was teleported to <blue>[1]</blue>!");

If you want to send your message now, you need to enter what should fill this placeholder, by providing an Array of them via the MessageAPI. It is important, that for example your replacer [0] needs to be filled by the first entry in the array and for example your [7] by the eight entry in your array! Let's take a look at what it could look like to send the message registered above:

MessageRecipient messageRecipient = new DummyMessageRecipient();
API.get().getMessageApi().sendMessage("here.goes.your.message.key", messageRecipient, new String[]{"DSeeLP","Spawn"});

(for this example I used a DummyMessageRecipeint, you would need to use a proper recipient here)

Untrusted Replacements

As you might have guessed, if there is a "trusted replacement" there needs to be an untrusted too. This Replacement is what I suggest you to use in all cases where possible, to ensure maximum stability and integrity of your messages! The difference between the untrusted and the trusted replacement is very easy to understand: "The untrusted replacement does not allow miniMessage tags". This means that all tags like <green> will be visible as "Text" in the final message. This denies users from entering tags into messages or stuff like this. The only difference you need to make while using this replacement is that you need to alter your pattern a bit. The Pattern for an untrusted replacement uses { & } instead of [ & ]. All of the sending processes is exactly the same as the process for the trusted Replacement