It would be nice to have a separate chat event for messages that gets sent as chat, but should not get the normal chat formatting. This could for example be used to replace or remove word from commands that also function as chat, but should not get the normal chat formatting.
This is currently possible by using a MessageChannelEvent, but that one can't be cancelled, so it's more of a dirty hack.
E.G.
We currently have MessageChannel.Chat
Private messages should be counted as chat, but not formatted as chat, as should /say and /me commands.
This idea means having some sort of a MessageChannel.Chat.Global which would be the standard chat formatting, leaving plugins to be able to implement MessageChannel.Chat.PM
Plugins wishing to do text replacements could listen to .Chat and cover all usecases of chat, without stepping on "primary formatting" plugins responsible for how the global chat should look.
Well, from what I know, your best bet is to insert a named cause (perhaps "type", "pm" or "type", "global") into the message channel cause and then use message channels to format it as you want. For example, say you want to ignore any messages that are not private messages. You would insert the "type" "pm" named cause into the event when you call it, then in a listener, set the message channel to something like this:
MessageChannel#combined(new PMChannel(), event.getChannel().get())
Of course, this relies on the event having a channel to begin with, but if it is to be sent to anyone this is a safe call. You can then specify in the PMChannel#transform(Object sender, MessageReceiver recipient, Text original, ChatType type) method how the pm should be formatted. The original text message in the message channel will be what other plugins modify the message to be (for instance, a swear word removed from it), and then you can format it as you please.
From what I can tell, this is what would work best as ryantheleach has explained it. Because the MessageChannel#combined() method does transforming in order of channels supplied to it, you can decide what channels format the message in order. This could allow for a ChatMessageChannel to format first, then a PMMessageChannel or GlobalMessageChannel to do their formatting afterwards. You can then edit words or whatever in the ChatMessageChannel object and then format messages in the others. The only caveat is that this relies on other plugins not submitting their own formatting message channels after yours, however there isn't really anything you can do about that until ways for plugins to communicate are provided.
I hope this helped!
The problem I see with that approach is twofold.
First of you loose basically all the advantages of doing chat formating in the event itself if you instead use channels for it as you can no longer differentiate between the header, body and footer of the message.
The bigger problem however is that it is an completely opt in system. Yeah sure, more freedom is good, but if you actually look around, none of the big Chat plugins use the header, body footer, system, and instead just use toPlain() or similar, which interferes quite a bit with plugins that do use that part of the API. To have a type parameter in the cause, and format based on that could allow more freedom (as long as people actually followed it), but I don't feel it is quite as good a solution as having different events.
Having a cause could work well, but SpongeAPI would need to provide a number of inbuilt causes for it to be useful.
I have a problem with the way ryan suggested the events be added, however.
As far as I can tell, there are only a few possible ways of solving the problem:
Adding new events (as you have stated):
Allowing formatters to combine:
Having a MessageType object stored in the event:
Using MessageChannels:
You could, of course, try to create a pull request that gives MessageChannels the ability to view header, body and footer as separate objects (perhaps pass the event's TextFormatter or a TextFormatter generated with the send method instead of the original text, and then return said formatter), however for the time being there are no real solutions that cover what you want. Events are probably the closest, however they stifle the ability for plugins to handle separate events as separate messages through internal means.
I've tried to list the pro's and con's of each method, hopefully this can help people with this for now.
From Discord:
"
SquidDev - Today at 1:11 AM
Hello! I've recently had an weird cross-mod interaction which, while no mod is really at fault, probably counts as a bug. Just thought I'd chuck it here to see if anyone had any thoughts.
Nucleus has a "staff chat" system, which forwards chat messages to a separate MessageChannel. However, posting messages will also fire Forge's ServerChatEvent - this will then be picked up by Computronics' chat boxes, allowing any user to read staff chat.
This is obviously undesirable, but I can't see any solution to this which isn't going to cause more problems than it solves.
"
Given causes, would it be worth firing the chat event intertwined with another event, with the OG event as the cause?
This would let people filter chat events for death etc to do death formatting.
This would have the added advantage of the chat event being able to be cancelled as well.
We could definitely do with a way to mark message channels as "for chat-related modification" and "for chat-related global readability".
Most helpful comment
From Discord:
"
SquidDev - Today at 1:11 AM
Hello! I've recently had an weird cross-mod interaction which, while no mod is really at fault, probably counts as a bug. Just thought I'd chuck it here to see if anyone had any thoughts.
Nucleus has a "staff chat" system, which forwards chat messages to a separate MessageChannel. However, posting messages will also fire Forge's ServerChatEvent - this will then be picked up by Computronics' chat boxes, allowing any user to read staff chat.
This is obviously undesirable, but I can't see any solution to this which isn't going to cause more problems than it solves.
"