mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-16 13:11:40 +01:00
Merge pull request #275 from Minestom/respect-client-chat-settings
Respect client chat settings
This commit is contained in:
commit
0a9fa31804
@ -12,7 +12,8 @@ import net.kyori.adventure.title.Title;
|
|||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
import net.minestom.server.network.packet.server.play.ChatMessagePacket;
|
import net.minestom.server.message.ChatPosition;
|
||||||
|
import net.minestom.server.message.Messenger;
|
||||||
import net.minestom.server.network.packet.server.play.PlayerListHeaderAndFooterPacket;
|
import net.minestom.server.network.packet.server.play.PlayerListHeaderAndFooterPacket;
|
||||||
import net.minestom.server.network.packet.server.play.TitlePacket;
|
import net.minestom.server.network.packet.server.play.TitlePacket;
|
||||||
import net.minestom.server.utils.PacketUtils;
|
import net.minestom.server.utils.PacketUtils;
|
||||||
@ -46,7 +47,7 @@ public interface PacketGroupingAudience extends ForwardingAudience {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
|
default void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
|
||||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new ChatMessagePacket(message, ChatMessagePacket.Position.fromMessageType(type), source.uuid()));
|
Messenger.sendMessage(this.getPlayers(), message, ChatPosition.fromMessageType(type), source.uuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -38,12 +38,15 @@ import net.minestom.server.event.player.*;
|
|||||||
import net.minestom.server.instance.Chunk;
|
import net.minestom.server.instance.Chunk;
|
||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
import net.minestom.server.instance.block.CustomBlock;
|
import net.minestom.server.instance.block.CustomBlock;
|
||||||
|
import net.minestom.server.message.ChatMessageType;
|
||||||
|
import net.minestom.server.message.ChatPosition;
|
||||||
import net.minestom.server.inventory.Inventory;
|
import net.minestom.server.inventory.Inventory;
|
||||||
import net.minestom.server.inventory.PlayerInventory;
|
import net.minestom.server.inventory.PlayerInventory;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.item.Material;
|
import net.minestom.server.item.Material;
|
||||||
import net.minestom.server.item.metadata.WrittenBookMeta;
|
import net.minestom.server.item.metadata.WrittenBookMeta;
|
||||||
import net.minestom.server.listener.PlayerDiggingListener;
|
import net.minestom.server.listener.PlayerDiggingListener;
|
||||||
|
import net.minestom.server.message.Messenger;
|
||||||
import net.minestom.server.network.ConnectionManager;
|
import net.minestom.server.network.ConnectionManager;
|
||||||
import net.minestom.server.network.ConnectionState;
|
import net.minestom.server.network.ConnectionState;
|
||||||
import net.minestom.server.network.PlayerProvider;
|
import net.minestom.server.network.PlayerProvider;
|
||||||
@ -730,8 +733,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
|
public void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
|
||||||
ChatMessagePacket chatMessagePacket = new ChatMessagePacket(message, ChatMessagePacket.Position.fromMessageType(type), source.uuid());
|
Messenger.sendMessage(this, message, ChatPosition.fromMessageType(type), source.uuid());
|
||||||
playerConnection.sendPacket(chatMessagePacket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2584,6 +2586,10 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
RIGHT
|
RIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated See {@link ChatMessageType}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public enum ChatMode {
|
public enum ChatMode {
|
||||||
ENABLED,
|
ENABLED,
|
||||||
COMMANDS_ONLY,
|
COMMANDS_ONLY,
|
||||||
@ -2594,7 +2600,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
|
|
||||||
private String locale;
|
private String locale;
|
||||||
private byte viewDistance;
|
private byte viewDistance;
|
||||||
private ChatMode chatMode;
|
private ChatMessageType chatMessageType;
|
||||||
private boolean chatColors;
|
private boolean chatColors;
|
||||||
private byte displayedSkinParts;
|
private byte displayedSkinParts;
|
||||||
private MainHand mainHand;
|
private MainHand mainHand;
|
||||||
@ -2625,9 +2631,20 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
* Gets the player chat mode.
|
* Gets the player chat mode.
|
||||||
*
|
*
|
||||||
* @return the player chat mode
|
* @return the player chat mode
|
||||||
|
* @deprecated Use {@link #getChatMessageType()}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public ChatMode getChatMode() {
|
public ChatMode getChatMode() {
|
||||||
return chatMode;
|
return ChatMode.values()[chatMessageType.ordinal()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the messages this player wants to receive.
|
||||||
|
*
|
||||||
|
* @return the messages
|
||||||
|
*/
|
||||||
|
public @Nullable ChatMessageType getChatMessageType() {
|
||||||
|
return chatMessageType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2659,19 +2676,19 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
*
|
*
|
||||||
* @param locale the player locale
|
* @param locale the player locale
|
||||||
* @param viewDistance the player view distance
|
* @param viewDistance the player view distance
|
||||||
* @param chatMode the player chat mode
|
* @param chatMessageType the chat messages the player wishes to receive
|
||||||
* @param chatColors the player chat colors
|
* @param chatColors if chat colors should be displayed
|
||||||
* @param displayedSkinParts the player displayed skin parts
|
* @param displayedSkinParts the player displayed skin parts
|
||||||
* @param mainHand the player main hand
|
* @param mainHand the player main hand
|
||||||
*/
|
*/
|
||||||
public void refresh(String locale, byte viewDistance, ChatMode chatMode, boolean chatColors,
|
public void refresh(String locale, byte viewDistance, ChatMessageType chatMessageType, boolean chatColors,
|
||||||
byte displayedSkinParts, MainHand mainHand) {
|
byte displayedSkinParts, MainHand mainHand) {
|
||||||
|
|
||||||
final boolean viewDistanceChanged = this.viewDistance != viewDistance;
|
final boolean viewDistanceChanged = this.viewDistance != viewDistance;
|
||||||
|
|
||||||
this.locale = locale;
|
this.locale = locale;
|
||||||
this.viewDistance = viewDistance;
|
this.viewDistance = viewDistance;
|
||||||
this.chatMode = chatMode;
|
this.chatMessageType = chatMessageType;
|
||||||
this.chatColors = chatColors;
|
this.chatColors = chatColors;
|
||||||
this.displayedSkinParts = displayedSkinParts;
|
this.displayedSkinParts = displayedSkinParts;
|
||||||
this.mainHand = mainHand;
|
this.mainHand = mainHand;
|
||||||
|
@ -6,10 +6,10 @@ import net.minestom.server.MinecraftServer;
|
|||||||
import net.minestom.server.command.CommandManager;
|
import net.minestom.server.command.CommandManager;
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
import net.minestom.server.event.player.PlayerChatEvent;
|
import net.minestom.server.event.player.PlayerChatEvent;
|
||||||
|
import net.minestom.server.message.ChatPosition;
|
||||||
|
import net.minestom.server.message.Messenger;
|
||||||
import net.minestom.server.network.ConnectionManager;
|
import net.minestom.server.network.ConnectionManager;
|
||||||
import net.minestom.server.network.packet.client.play.ClientChatMessagePacket;
|
import net.minestom.server.network.packet.client.play.ClientChatMessagePacket;
|
||||||
import net.minestom.server.network.packet.server.play.ChatMessagePacket;
|
|
||||||
import net.minestom.server.utils.PacketUtils;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -26,21 +26,30 @@ public class ChatMessageListener {
|
|||||||
final String cmdPrefix = CommandManager.COMMAND_PREFIX;
|
final String cmdPrefix = CommandManager.COMMAND_PREFIX;
|
||||||
if (message.startsWith(cmdPrefix)) {
|
if (message.startsWith(cmdPrefix)) {
|
||||||
// The message is a command
|
// The message is a command
|
||||||
message = message.replaceFirst(cmdPrefix, "");
|
final String command = message.replaceFirst(cmdPrefix, "");
|
||||||
|
|
||||||
COMMAND_MANAGER.execute(player, message);
|
// check if we can receive commands
|
||||||
|
if (Messenger.canReceiveCommand(player)) {
|
||||||
|
COMMAND_MANAGER.execute(player, command);
|
||||||
|
} else {
|
||||||
|
Messenger.sendRejectionMessage(player);
|
||||||
|
}
|
||||||
|
|
||||||
// Do not call chat event
|
// Do not call chat event
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if we can receive messages
|
||||||
|
if (!Messenger.canReceiveMessage(player)) {
|
||||||
|
Messenger.sendRejectionMessage(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final Collection<Player> players = CONNECTION_MANAGER.getOnlinePlayers();
|
final Collection<Player> players = CONNECTION_MANAGER.getOnlinePlayers();
|
||||||
String finalMessage = message;
|
PlayerChatEvent playerChatEvent = new PlayerChatEvent(player, players, () -> buildDefaultChatMessage(player, message), message);
|
||||||
PlayerChatEvent playerChatEvent = new PlayerChatEvent(player, players, () -> buildDefaultChatMessage(player, finalMessage), message);
|
|
||||||
|
|
||||||
// Call the event
|
// Call the event
|
||||||
player.callCancellableEvent(PlayerChatEvent.class, playerChatEvent, () -> {
|
player.callCancellableEvent(PlayerChatEvent.class, playerChatEvent, () -> {
|
||||||
|
|
||||||
final Function<PlayerChatEvent, Component> formatFunction = playerChatEvent.getChatFormatFunction();
|
final Function<PlayerChatEvent, Component> formatFunction = playerChatEvent.getChatFormatFunction();
|
||||||
|
|
||||||
Component textObject;
|
Component textObject;
|
||||||
@ -55,15 +64,10 @@ public class ChatMessageListener {
|
|||||||
|
|
||||||
final Collection<Player> recipients = playerChatEvent.getRecipients();
|
final Collection<Player> recipients = playerChatEvent.getRecipients();
|
||||||
if (!recipients.isEmpty()) {
|
if (!recipients.isEmpty()) {
|
||||||
// Send the message with the correct player UUID
|
// delegate to the messenger to avoid sending messages we shouldn't be
|
||||||
ChatMessagePacket chatMessagePacket =
|
Messenger.sendMessage(recipients, textObject, ChatPosition.CHAT, player.getUuid());
|
||||||
new ChatMessagePacket(textObject, ChatMessagePacket.Position.CHAT, player.getUuid());
|
|
||||||
|
|
||||||
PacketUtils.sendGroupedPacket(recipients, chatMessagePacket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NotNull Component buildDefaultChatMessage(@NotNull Player player, @NotNull String message) {
|
private static @NotNull Component buildDefaultChatMessage(@NotNull Player player, @NotNull String message) {
|
||||||
|
@ -8,7 +8,7 @@ public class SettingsListener {
|
|||||||
|
|
||||||
public static void listener(ClientSettingsPacket packet, Player player) {
|
public static void listener(ClientSettingsPacket packet, Player player) {
|
||||||
Player.PlayerSettings settings = player.getSettings();
|
Player.PlayerSettings settings = player.getSettings();
|
||||||
settings.refresh(packet.locale, packet.viewDistance, packet.chatMode, packet.chatColors, packet.displayedSkinParts, packet.mainHand);
|
settings.refresh(packet.locale, packet.viewDistance, packet.chatMessageType, packet.chatColors, packet.displayedSkinParts, packet.mainHand);
|
||||||
|
|
||||||
PlayerSettingsChangeEvent playerSettingsChangeEvent = new PlayerSettingsChangeEvent(player);
|
PlayerSettingsChangeEvent playerSettingsChangeEvent = new PlayerSettingsChangeEvent(player);
|
||||||
player.callEvent(PlayerSettingsChangeEvent.class, playerSettingsChangeEvent);
|
player.callEvent(PlayerSettingsChangeEvent.class, playerSettingsChangeEvent);
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
package net.minestom.server.message;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The messages that a player is willing to receive.
|
||||||
|
*/
|
||||||
|
public enum ChatMessageType {
|
||||||
|
/**
|
||||||
|
* The client wants all chat messages.
|
||||||
|
*/
|
||||||
|
FULL(EnumSet.allOf(ChatPosition.class)),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client only wants messages from commands, or system messages.
|
||||||
|
*/
|
||||||
|
SYSTEM(EnumSet.of(ChatPosition.SYSTEM_MESSAGE, ChatPosition.GAME_INFO)),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client doesn't want any messages.
|
||||||
|
*/
|
||||||
|
NONE(EnumSet.of(ChatPosition.GAME_INFO));
|
||||||
|
|
||||||
|
private final EnumSet<ChatPosition> acceptedPositions;
|
||||||
|
|
||||||
|
ChatMessageType(@NotNull EnumSet<ChatPosition> acceptedPositions) {
|
||||||
|
this.acceptedPositions = acceptedPositions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this message type is accepting of messages from a given position.
|
||||||
|
*
|
||||||
|
* @param chatPosition the position
|
||||||
|
* @return if the message is accepted
|
||||||
|
*/
|
||||||
|
public boolean accepts(@NotNull ChatPosition chatPosition) {
|
||||||
|
return this.acceptedPositions.contains(chatPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the packet ID for this chat message type.
|
||||||
|
*
|
||||||
|
* @return the packet ID
|
||||||
|
*/
|
||||||
|
public int getPacketID() {
|
||||||
|
return this.ordinal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a chat message type from a packet ID.
|
||||||
|
*
|
||||||
|
* @param id the packet ID
|
||||||
|
* @return the chat message type
|
||||||
|
*/
|
||||||
|
public static @NotNull ChatMessageType fromPacketID(int id) {
|
||||||
|
switch (id) {
|
||||||
|
case 0: return FULL;
|
||||||
|
case 1: return SYSTEM;
|
||||||
|
case 2: return NONE;
|
||||||
|
default: throw new IllegalArgumentException("id must be between 0-2 (inclusive)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
src/main/java/net/minestom/server/message/ChatPosition.java
Normal file
79
src/main/java/net/minestom/server/message/ChatPosition.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package net.minestom.server.message;
|
||||||
|
|
||||||
|
import net.kyori.adventure.audience.MessageType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The different positions for chat messages.
|
||||||
|
*/
|
||||||
|
public enum ChatPosition {
|
||||||
|
/**
|
||||||
|
* A player-initiated chat message.
|
||||||
|
*/
|
||||||
|
CHAT(MessageType.CHAT),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feedback from running a command or other system messages.
|
||||||
|
*/
|
||||||
|
SYSTEM_MESSAGE(MessageType.SYSTEM),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Game state information displayed above the hot bar.
|
||||||
|
*/
|
||||||
|
GAME_INFO(null);
|
||||||
|
|
||||||
|
private final MessageType messageType;
|
||||||
|
|
||||||
|
ChatPosition(@NotNull MessageType messageType) {
|
||||||
|
this.messageType = messageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Adventure message type from this position. Note that there is no
|
||||||
|
* message type for {@link #GAME_INFO}, as Adventure uses the title methods for this.
|
||||||
|
*
|
||||||
|
* @return the message type, if any
|
||||||
|
*/
|
||||||
|
public @Nullable MessageType getMessageType() {
|
||||||
|
return this.messageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the packet ID of this chat position.
|
||||||
|
*
|
||||||
|
* @return the ID
|
||||||
|
*/
|
||||||
|
public byte getID() {
|
||||||
|
return (byte) this.ordinal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a position from an Adventure message type.
|
||||||
|
*
|
||||||
|
* @param messageType the message type
|
||||||
|
* @return the position
|
||||||
|
*/
|
||||||
|
public static @NotNull ChatPosition fromMessageType(@NotNull MessageType messageType) {
|
||||||
|
switch (messageType) {
|
||||||
|
case CHAT: return CHAT;
|
||||||
|
case SYSTEM: return SYSTEM_MESSAGE;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Cannot get position from message type!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a position from a packet ID.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @return the chat position
|
||||||
|
*/
|
||||||
|
public static @NotNull ChatPosition fromPacketID(byte id) {
|
||||||
|
switch (id) {
|
||||||
|
case 0: return CHAT;
|
||||||
|
case 1: return SYSTEM_MESSAGE;
|
||||||
|
case 2: return GAME_INFO;
|
||||||
|
default: throw new IllegalArgumentException("id must be between 0-2 (inclusive)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
94
src/main/java/net/minestom/server/message/Messenger.java
Normal file
94
src/main/java/net/minestom/server/message/Messenger.java
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package net.minestom.server.message;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.minestom.server.entity.Player;
|
||||||
|
import net.minestom.server.network.packet.server.play.ChatMessagePacket;
|
||||||
|
import net.minestom.server.utils.PacketUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to handle client chat settings.
|
||||||
|
*/
|
||||||
|
public class Messenger {
|
||||||
|
/**
|
||||||
|
* The message sent to the client if they send a chat message but it is rejected by the server.
|
||||||
|
*/
|
||||||
|
public static final Component CANNOT_SEND_MESSAGE = Component.translatable("chat.cannotSend", NamedTextColor.RED);
|
||||||
|
|
||||||
|
private static final ChatMessagePacket CANNOT_SEND_PACKET = new ChatMessagePacket(CANNOT_SEND_MESSAGE, ChatPosition.SYSTEM_MESSAGE, null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a message to a player, respecting their chat settings.
|
||||||
|
*
|
||||||
|
* @param player the player
|
||||||
|
* @param message the message
|
||||||
|
* @param position the position
|
||||||
|
* @param uuid the UUID of the sender, if any
|
||||||
|
* @return if the message was sent
|
||||||
|
*/
|
||||||
|
public static boolean sendMessage(@NotNull Player player, @NotNull Component message, @NotNull ChatPosition position, @Nullable UUID uuid) {
|
||||||
|
if (getChatMessageType(player).accepts(position)) {
|
||||||
|
player.getPlayerConnection().sendPacket(new ChatMessagePacket(message, position, uuid));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a message to some players, respecting their chat settings.
|
||||||
|
*
|
||||||
|
* @param players the players
|
||||||
|
* @param message the message
|
||||||
|
* @param position the position
|
||||||
|
* @param uuid the UUID of the sender, if any
|
||||||
|
*/
|
||||||
|
public static void sendMessage(@NotNull Collection<Player> players, @NotNull Component message,
|
||||||
|
@NotNull ChatPosition position, @Nullable UUID uuid) {
|
||||||
|
PacketUtils.sendGroupedPacket(players, new ChatMessagePacket(message, position, uuid),
|
||||||
|
player -> getChatMessageType(player).accepts(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the server should receive messages from a player, given their chat settings.
|
||||||
|
*
|
||||||
|
* @param player the player
|
||||||
|
* @return if the server should receive messages from them
|
||||||
|
*/
|
||||||
|
public static boolean canReceiveMessage(@NotNull Player player) {
|
||||||
|
return getChatMessageType(player) == ChatMessageType.FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the server should receive commands from a player, given their chat settings.
|
||||||
|
*
|
||||||
|
* @param player the player
|
||||||
|
* @return if the server should receive commands from them
|
||||||
|
*/
|
||||||
|
public static boolean canReceiveCommand(@NotNull Player player) {
|
||||||
|
return getChatMessageType(player) != ChatMessageType.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a message to the player informing them we are rejecting their message or command.
|
||||||
|
*
|
||||||
|
* @param player the player
|
||||||
|
*/
|
||||||
|
public static void sendRejectionMessage(@NotNull Player player) {
|
||||||
|
player.getPlayerConnection().sendPacket(CANNOT_SEND_PACKET, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the chat message type for a player, returning {@link ChatMessageType#FULL} if not set.
|
||||||
|
*
|
||||||
|
* @param player the player
|
||||||
|
* @return the chat message type
|
||||||
|
*/
|
||||||
|
private static @NotNull ChatMessageType getChatMessageType(@NotNull Player player) {
|
||||||
|
return Objects.requireNonNullElse(player.getSettings().getChatMessageType(), ChatMessageType.FULL);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package net.minestom.server.network.packet.client.play;
|
package net.minestom.server.network.packet.client.play;
|
||||||
|
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
|
import net.minestom.server.message.ChatMessageType;
|
||||||
import net.minestom.server.network.packet.client.ClientPlayPacket;
|
import net.minestom.server.network.packet.client.ClientPlayPacket;
|
||||||
import net.minestom.server.utils.binary.BinaryReader;
|
import net.minestom.server.utils.binary.BinaryReader;
|
||||||
import net.minestom.server.utils.binary.BinaryWriter;
|
import net.minestom.server.utils.binary.BinaryWriter;
|
||||||
@ -10,7 +11,7 @@ public class ClientSettingsPacket extends ClientPlayPacket {
|
|||||||
|
|
||||||
public String locale = "";
|
public String locale = "";
|
||||||
public byte viewDistance;
|
public byte viewDistance;
|
||||||
public Player.ChatMode chatMode = Player.ChatMode.ENABLED;
|
public ChatMessageType chatMessageType = ChatMessageType.FULL;
|
||||||
public boolean chatColors;
|
public boolean chatColors;
|
||||||
public byte displayedSkinParts;
|
public byte displayedSkinParts;
|
||||||
public Player.MainHand mainHand = Player.MainHand.RIGHT;
|
public Player.MainHand mainHand = Player.MainHand.RIGHT;
|
||||||
@ -19,7 +20,7 @@ public class ClientSettingsPacket extends ClientPlayPacket {
|
|||||||
public void read(@NotNull BinaryReader reader) {
|
public void read(@NotNull BinaryReader reader) {
|
||||||
this.locale = reader.readSizedString(128);
|
this.locale = reader.readSizedString(128);
|
||||||
this.viewDistance = reader.readByte();
|
this.viewDistance = reader.readByte();
|
||||||
this.chatMode = Player.ChatMode.values()[reader.readVarInt()];
|
this.chatMessageType = ChatMessageType.fromPacketID(reader.readVarInt());
|
||||||
this.chatColors = reader.readBoolean();
|
this.chatColors = reader.readBoolean();
|
||||||
this.displayedSkinParts = reader.readByte();
|
this.displayedSkinParts = reader.readByte();
|
||||||
this.mainHand = Player.MainHand.values()[reader.readVarInt()];
|
this.mainHand = Player.MainHand.values()[reader.readVarInt()];
|
||||||
@ -31,7 +32,7 @@ public class ClientSettingsPacket extends ClientPlayPacket {
|
|||||||
throw new IllegalArgumentException("Locale cannot be longer than 128 characters.");
|
throw new IllegalArgumentException("Locale cannot be longer than 128 characters.");
|
||||||
writer.writeSizedString(locale);
|
writer.writeSizedString(locale);
|
||||||
writer.writeByte(viewDistance);
|
writer.writeByte(viewDistance);
|
||||||
writer.writeVarInt(chatMode.ordinal());
|
writer.writeVarInt(chatMessageType.getPacketID());
|
||||||
writer.writeBoolean(chatColors);
|
writer.writeBoolean(chatColors);
|
||||||
writer.writeByte(displayedSkinParts);
|
writer.writeByte(displayedSkinParts);
|
||||||
writer.writeVarInt(mainHand.ordinal());
|
writer.writeVarInt(mainHand.ordinal());
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.minestom.server.network.packet.server.play;
|
package net.minestom.server.network.packet.server.play;
|
||||||
|
|
||||||
import net.kyori.adventure.audience.MessageType;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.minestom.server.message.ChatPosition;
|
||||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
@ -12,6 +12,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
@ -22,21 +23,19 @@ public class ChatMessagePacket implements ComponentHoldingServerPacket {
|
|||||||
private static final UUID NULL_UUID = new UUID(0, 0);
|
private static final UUID NULL_UUID = new UUID(0, 0);
|
||||||
|
|
||||||
public Component message;
|
public Component message;
|
||||||
public Position position;
|
public ChatPosition position;
|
||||||
public UUID uuid;
|
public UUID uuid;
|
||||||
|
|
||||||
public ChatMessagePacket() {
|
public ChatMessagePacket() {
|
||||||
this(Component.empty(), Position.CHAT);
|
this.message = Component.empty();
|
||||||
|
this.position = ChatPosition.SYSTEM_MESSAGE;
|
||||||
|
this.uuid = NULL_UUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChatMessagePacket(Component message, Position position, UUID uuid) {
|
public ChatMessagePacket(@NotNull Component message, @NotNull ChatPosition position, @Nullable UUID uuid) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
this.uuid = uuid;
|
this.uuid = Objects.requireNonNullElse(uuid, NULL_UUID);
|
||||||
}
|
|
||||||
|
|
||||||
public ChatMessagePacket(Component message, Position position) {
|
|
||||||
this(message, position, NULL_UUID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -49,7 +48,7 @@ public class ChatMessagePacket implements ComponentHoldingServerPacket {
|
|||||||
@Override
|
@Override
|
||||||
public void read(@NotNull BinaryReader reader) {
|
public void read(@NotNull BinaryReader reader) {
|
||||||
message = reader.readComponent(Integer.MAX_VALUE);
|
message = reader.readComponent(Integer.MAX_VALUE);
|
||||||
position = Position.values()[reader.readByte()];
|
position = ChatPosition.fromPacketID(reader.readByte());
|
||||||
uuid = reader.readUuid();
|
uuid = reader.readUuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,41 +66,4 @@ public class ChatMessagePacket implements ComponentHoldingServerPacket {
|
|||||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||||
return new ChatMessagePacket(operator.apply(message), position, uuid);
|
return new ChatMessagePacket(operator.apply(message), position, uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Position {
|
|
||||||
CHAT(MessageType.CHAT),
|
|
||||||
SYSTEM_MESSAGE(MessageType.SYSTEM),
|
|
||||||
GAME_INFO(null);
|
|
||||||
|
|
||||||
private final MessageType messageType;
|
|
||||||
|
|
||||||
Position(MessageType messageType) {
|
|
||||||
this.messageType = messageType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Adventure message type from this position. Note that there is no
|
|
||||||
* message type for {@link #GAME_INFO}, as Adventure uses the title methods for this.
|
|
||||||
*
|
|
||||||
* @return the message type, if any
|
|
||||||
*/
|
|
||||||
public @Nullable MessageType getMessageType() {
|
|
||||||
return this.messageType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a position from an Adventure message type.
|
|
||||||
*
|
|
||||||
* @param messageType the message type
|
|
||||||
*
|
|
||||||
* @return the position
|
|
||||||
*/
|
|
||||||
public static @NotNull Position fromMessageType(@NotNull MessageType messageType) {
|
|
||||||
switch (messageType) {
|
|
||||||
case CHAT: return CHAT;
|
|
||||||
case SYSTEM: return SYSTEM_MESSAGE;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Cannot get position from message type!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ public abstract class PlayerConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes the packet and send it to the client, skipping the translation phase.
|
* Serializes the packet and send it to the client, optionally skipping the translation phase.
|
||||||
* <p>
|
* <p>
|
||||||
* Also responsible for executing {@link ConnectionManager#onPacketSend(ServerPacketConsumer)} consumers.
|
* Also responsible for executing {@link ConnectionManager#onPacketSend(ServerPacketConsumer)} consumers.
|
||||||
*
|
*
|
||||||
|
@ -1,24 +1,32 @@
|
|||||||
package demo.commands;
|
package demo.commands;
|
||||||
|
|
||||||
|
import net.kyori.adventure.audience.MessageType;
|
||||||
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.event.ClickEvent;
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
import net.minestom.server.command.builder.Command;
|
import net.minestom.server.command.builder.Command;
|
||||||
import net.minestom.server.command.builder.arguments.ArgumentType;
|
import net.minestom.server.command.builder.arguments.ArgumentType;
|
||||||
import net.minestom.server.command.builder.arguments.minecraft.ArgumentComponent;
|
import net.minestom.server.command.builder.arguments.minecraft.ArgumentComponent;
|
||||||
|
import net.minestom.server.command.builder.arguments.minecraft.ArgumentUUID;
|
||||||
|
|
||||||
public class EchoCommand extends Command {
|
public class EchoCommand extends Command {
|
||||||
public EchoCommand() {
|
public EchoCommand() {
|
||||||
super("echo");
|
super("echo");
|
||||||
|
|
||||||
this.setDefaultExecutor((sender, context) -> sender.sendMessage(
|
this.setDefaultExecutor((sender, context) -> sender.sendMessage(
|
||||||
Component.text("Usage: /echo <json>")
|
Component.text("Usage: /echo <json> [uuid]")
|
||||||
.hoverEvent(Component.text("Click to get this command.")
|
.hoverEvent(Component.text("Click to get this command.")
|
||||||
.clickEvent(ClickEvent.suggestCommand("/echo ")))));
|
.clickEvent(ClickEvent.suggestCommand("/echo ")))));
|
||||||
|
|
||||||
ArgumentComponent json = ArgumentType.Component("json");
|
ArgumentComponent json = ArgumentType.Component("json");
|
||||||
|
ArgumentUUID uuid = ArgumentType.UUID("uuid");
|
||||||
|
|
||||||
this.addSyntax((sender, context) -> {
|
this.addSyntax((sender, context) -> {
|
||||||
sender.sendMessage(context.get(json));
|
sender.sendMessage(context.get(json));
|
||||||
}, json);
|
}, json);
|
||||||
|
|
||||||
|
this.addSyntax((sender, context) -> {
|
||||||
|
sender.sendMessage(Identity.identity(context.get(uuid)), context.get(json), MessageType.CHAT);
|
||||||
|
}, uuid, json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user