Message Channels
Dans Sponge, tous les objets auxquels des messages peuvent être envoyés implémentent l’interface MessageReceiver. Un MessageChannel est un dispositif qui peut envoyer des messages à un nombre arbitraire de MessageReceiver
s et même effectuer des actions tels que des mises en forme spécifiques au destinataire du message.
Sélectionner les Destinataires du Message
À l’intérieur de l’interface MessageChannel
il y a des constantes et des méthodes statiques qui peuvent être utilisées pour obtenir ou créer des canaux couramment utilisés. Il y a également d’autres classes et interfaces qui peuvent être utilisées pour créer un MessageChannel
, comme AbstractMutableMessageChannel et MutableMessageChannel. Une liste complète peut être trouvée dans org.spongepowered.api.text.channel et ses sous-packages.
Diffusion
Le canal le plus courant sera le canal de diffusion. Il peut être obtenu soit depuis le Server via la méthode Server#getBroadcastChannel() ou soit depuis les constantes MessageChannel#TO_PLAYERS ou MessageChannel#TO_ALL. La seule différence est que TO_ALL
n’inclut pas seulement tous les joueurs connectés au serveur mais aussi la Console
du serveur.
Le canal retourné par getBroadcastsChannel()
sera généralement le canal MessageChannel.TO_ALL
, cependant un canal différent peut être défini en utilisant la méthode Server#setBroadcastChannel(MessageChannel).
Envoyer à une liste fixe de MessageReceivers
Il est également possible d’envoyer un message non pas à tous les joueurs connectés, mais à un nombre de destinataires sélectionnés à la main. Cela peut être fait en passant la liste des destinataires voulus à la méthode MessageChannel#fixed(MessageReceiver…). Contrairement à la plupart des autres canaux, la liste des destinataires ne sera pas générée dynamiquement chaque fois que quelque chose est envoyé à travers le canal, mais reste statique pour le reste de son existence. Cependant, les références gardées sont faibles. Cela signifie que si par exemple un joueur se déconnecte et que l’objet Player correspondant est supprimé par le garbage collector de Java, ce joueur va aussi disparaître de la liste de destinaires des canaux.
Sélection basée sur les Permissions
Il est également possible de créer un canal qui envoie à tous les destinataires qui détiennent une permission spécifique. Le canal est obtenu à partir de la méthode MessageChannel#permission(String) avec la permission à vérifier en argument. Quand un message est alors envoyé par ce canal, il obtiendra tous les sujets depuis le PermissionService qui possèdent la permission donnée.
Combiner des Canaux
Il est également possible de combiner plusieurs canaux en un seul. Cela peut être fait en passant tous les canaux dans la méthode MessageChannel#combined(MessageChannel…). Le canal qui en résulte va relayer les messages à chaque destinataire qui est ciblé par au moins un des canaux combinés.
Envoyer des Messages
Une fois que vous avez obtenus un MessageChannel
vous pouvez envoyer un message via lui grâce à la méthode MessageChannel#send(Object, Text). Cette méthode est préférable à la méthode MessageChannel#send(Text), puisque l”Object
peut être utilisé pour l’identification ou pour effectuer d’autres actions diverses. Alternativement, vous pouvez utiliser un ChatType pour spécifier où est-ce que le message sera envoyé. Utiliser la méthode MessageChannel#send(Object, Text, ChatType) vous permettra d’y parvenir. Le canal transformera alors le message pour chaque destinataire et enverra le message transformé.
Application étendue: Canaux de discussion
Les message channels ont une application très utile, puisqu’ils peuvent être utilisés pour établir des canaux de discussion. Par exemple, vous pouvez établir un message channel pour chaque canal de discussion que vous souhaitez avoir. Ensuite, quand un MessageReceiver
rejoint un canal, comme avec /join <nom du canal>
, définissez simplement le MessageChannel
des MessageReceiver
s au canal approprié en utilisant MessageReceiver#setMessageChannel(MessageChannel). Cela va faire que tous les messages envoyés depuis le MessageReceiver
seront passés au MessageChannel
donné plutôt qu’à celui par défaut. Alternativement, vous pouvez écouter le MessageChannelEvent, et définir le MessageChannel
approprié en utilisant MessageChannelEvent#setChannel(MessageChannel). Passer null
à cette méthode va désinitialiser tous les canaux personnalisés, ce qui va faire que le message sera envoyé au MessageChannel original à la place.
Transformer les Messages
Vous pouvez appliquer un filtre à tous les Text
s qui passent à travers un MessageChannel
pour changer le message comme bon vous semble. C’est possible en héritant MessageChannel
et en réécrivant la méthode MessageChannel#transformMessage(Object, MessageReceiver, Text, ChatType) comme montré ci-dessous.
Exemple : Transformer les Messages
L’extrait de code suivant définit une classe AdminMessageChannel
qui réécrit la méthode par défaut transformMessage
. La nouvelle méthode transformMessage
va prendre le message original et ajouter un tag rouge [Admin]
au début du message.
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.text.channel.MessageChannel;
import org.spongepowered.api.text.channel.MessageReceiver;
import org.spongepowered.api.text.format.TextColors;
public class AdminMessageChannel implements MessageChannel {
@Override
public Optional<Text> transformMessage(Object sender, MessageReceiver recipient,
Text original) {
Text text = original;
text = Text.of(TextColors.RED, "[Admin]", TextColors.RESET, text);
return Optional.of(text);
}
@Override
public Collection<MessageReceiver> getMembers() {
return Collections.emptyList();
}
}
Notez que nous ne souhaitons pas définir d’autres récipients, nous retournons donc une collection vide dans la méthode MessageChannel#getMembers().
Grâce aux capacités des MessageChannel
s combinés, nous pouvez combiner nos AdminMessageChannel
nouvellement créés avec n’importe quel autre MessageChannel
. Maintenant si un player rejoint avec la permission myplugin.admin
, nous obtiendront le MessageChannel
auquel ses messages sont envoyés, le combiner avec un AdminMessageChannel
et définir le canal combiné au joueur. De cette manière tous ces messages seront envoyés à tous les joueurs spécifiés dans le canal original, mais en raison de l’ajout du AdminMessageChannel
, il sera préfixé d’un tag rouge [Admin]
.
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.network.ClientConnectionEvent;
private AdminMessageChannel adminChannel = new AdminMessageChannel();
@Listener
public void onClientConnectionJoin(ClientConnectionEvent.Join event) {
Player player = event.getTargetEntity();
if(player.hasPermission("myplugin.admin")) {
MessageChannel originalChannel = event.getOriginalChannel();
MessageChannel newChannel = MessageChannel.combined(originalChannel,
adminChannel);
player.setMessageChannel(newChannel);
}
}
Notez que cela va préfixer tous les messages se rapportant à un joueur. Cela inclut les messages de mort, les message de déconnexion, etc… Si vous souhaitez seulement préfixer les messages de chat, vous devrez écouter à l’événement MessageChannelEvent.Chat et définir le canal à l’événement et non au joueur. Cela se fait en utilisant event.setChannel(newChannel)
sur l’événement MessageChannelEvent.Chat
. Pour récupérer le joueur depuis l’événement pour vérifier les permissions, vous aurez besoin de récupérer un Player
depuis la Cause
de l’événement. C’est illustré ci-dessous :
Optional<Player> playerOptional = event.getCause().<Player>first(Player.class);
Plus d’informations sur les causes peuvent être trouvées sur la page des causes.
Note
En combinant plusieurs MessageChannel
s en définissant différentes transformations de messages, le Text
sera transformé dans l’ordre dans lequel les MessageChannel
s sont passés à la méthode MessageChannel#combined(MessageChannel... channels)
. Notez que toutes les transformations résultant en un Optional
vide seront ignorées sauf si elles sont effectuées par le dernier canal de la chaîne.
Message Channels Muables
Un MutableMessageChannel contient des méthodes permettant de modifier qui peut recevoir les messages envoyés à travers notre canal. Par conséquent, nous devons implémenter des méthodes pour effectuer des actions qui modifient nos membres. Pour faire ceci, nous allons simplement créer une classe nommée MutableAdminMessageChannel
qui va implémenter un MutableMessageChannel
.
import java.util.Set;
import java.util.WeakHashMap;
import org.spongepowered.api.text.channel.MutableMessageChannel;
public class MutableAdminMessageChannel implements MutableMessageChannel {
private Set<MessageReceiver> members;
public MutableAdminMessageChannel() {
this(Collections.emptySet());
}
public MutableAdminMessageChannel(Collection<MessageReceiver> members) {
this.members = Collections.newSetFromMap(new WeakHashMap<>());
this.members.addAll(members);
}
@Override
public Collection<MessageReceiver> getMembers() {
return Collections.unmodifiableSet(this.members);
}
@Override
public boolean addMember(MessageReceiver member) {
return this.members.add(member);
}
@Override
public boolean removeMember(MessageReceiver member) {
return this.members.remove(member);
}
@Override
public void clearMembers() {
this.members.clear();
}
@Override
public Optional<Text> transformMessage(Object sender, MessageReceiver recipient,
Text original) {
Text text = original;
if(this.members.contains(recipient)) {
text = Text.of(TextColors.RED, "[Admin]", TextColors.RESET, text);
}
return Optional.of(text);
}
}
La différence principale entre notre AdminMessageChannel
et notre nouveau MutableAdminMessageChannel
est que nous vérifions si le destinataire est dans la liste des membres avant de transformer le message. Si il y est, alors nous pouvons altérer le message qui est envoyé, en ajoutant le tag rouge [Admin]
. Dans notre méthode getMembers()
nous retournons un set immuable, pour que le set puisse seulement être modifié par les méthodes appropriées dans notre MutableAdminMessageChannel
.
Notez qu’une implémentation abstraite pour les MutableMessageChannel
s existe dans l’API Sponge comme AbstractMutableMessageChannel
. Notez également que nos membres ne persistent pas. Si un joueur devait quitter le serveur, alors il serait enlevé du set.
Modification des Membres
Pour tirer pleinement parti de nos MutableAdminMessageChannel
, nous devons être capable d’ajouter et d’enlever des membres du canal. Pour faire ceci, nous pouvons simplement appeler nos méthodes MutableMessageChannel#addMember(MessageReceiver) et MutableMessageChannel#removeMember(MessageReceiver) que nous avons implémentées précédemment lorsque nous avons besoin d’ajouter ou d’enlever un membre du set.