mirror of
https://github.com/FabricMC/fabric.git
synced 2025-04-03 10:39:57 -04:00
Added Client Message Events (#2646)
* Added Client Message Events
* Applied suggestions and fixed checkstyle
* Inject before fabric-command-api and updated Javadocs
* Updated Javadocs regarding client commands
* Update fabric-message-api-v1/src/client/resources/fabric-message-api-v1.client.mixins.json
Co-authored-by: Juuz <6596629+Juuxel@users.noreply.github.com>
* Updated Javadocs regarding commands
* Fixed duplicated package names
* Updated ClientMessageEvents.java Javadoc
Co-authored-by: Sideroo <109681866+Sideroo@users.noreply.github.com>
* Removed duplicated client commands Javadoc
* Added cancelled sending and receiving events
* Seperated send and receive events and changed event names
* Fixed checkstyle
* Added support for modifying messages
* Added client command test
* Added narration and message indicator support for modifying received messages
* Added tests for modifying messages
* Updated ClientReceiveMessageEvents#CHAT Javadocs
* Small Javadoc fixes
* Added Modify to names
* Always narrate original message
* Removed modifying receive chat message
* Split notify and modify events
* Fixed checkstyle
---------
Co-authored-by: Juuz <6596629+Juuxel@users.noreply.github.com>
Co-authored-by: Sideroo <109681866+Sideroo@users.noreply.github.com>
(cherry picked from commit c85585f870
)
This commit is contained in:
parent
81e8c5765a
commit
1ee8be400a
9 changed files with 791 additions and 2 deletions
fabric-message-api-v1
build.gradle
src
client
java/net/fabricmc/fabric
api/client/message/v1
mixin/client/message
resources
main/resources
testmod
|
@ -4,3 +4,7 @@ version = getSubprojectVersion(project)
|
|||
moduleDependencies(project, [
|
||||
'fabric-api-base'
|
||||
])
|
||||
|
||||
testDependencies(project, [
|
||||
'fabric-command-api-v2'
|
||||
])
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.client.message.v1;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.client.gui.hud.ChatHud;
|
||||
import net.minecraft.network.message.MessageType;
|
||||
import net.minecraft.network.message.SignedMessage;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
|
||||
/**
|
||||
* Contains client-side events triggered when receiving messages.
|
||||
*/
|
||||
public final class ClientReceiveMessageEvents {
|
||||
private ClientReceiveMessageEvents() {
|
||||
}
|
||||
|
||||
/**
|
||||
* An event triggered when the client receives a chat message,
|
||||
* which is any message sent by a player. Mods can use this to block the message.
|
||||
*
|
||||
* <p>If a listener returned {@code false}, the message will not be displayed,
|
||||
* the remaining listeners will not be called (if any), and
|
||||
* {@link #CHAT_CANCELED} will be triggered instead of {@link #CHAT}.
|
||||
*/
|
||||
public static final Event<AllowChat> ALLOW_CHAT = EventFactory.createArrayBacked(AllowChat.class, listeners -> (message, signedMessage, sender, params, receptionTimestamp) -> {
|
||||
for (AllowChat listener : listeners) {
|
||||
if (!listener.allowReceiveChatMessage(message, signedMessage, sender, params, receptionTimestamp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when the client receives a game message,
|
||||
* which is any message sent by the server.
|
||||
* Mods can use this to block the message or toggle overlay.
|
||||
*
|
||||
* <p>If a listener returned {@code false}, the message will not be displayed,
|
||||
* the remaining listeners will not be called (if any), and
|
||||
* {@link #GAME_CANCELED} will be triggered instead of {@link #MODIFY_GAME}.
|
||||
*
|
||||
* <p>Overlay is whether the message will be displayed in the action bar.
|
||||
* To toggle overlay, return false and call
|
||||
* {@link net.minecraft.client.network.ClientPlayerEntity#sendMessage(Text, boolean) ClientPlayerEntity.sendMessage(message, overlay)}.
|
||||
*/
|
||||
public static final Event<AllowGame> ALLOW_GAME = EventFactory.createArrayBacked(AllowGame.class, listeners -> (message, overlay) -> {
|
||||
for (AllowGame listener : listeners) {
|
||||
if (!listener.allowReceiveGameMessage(message, overlay)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when the client receives a game message,
|
||||
* which is any message sent by the server. Is not called when
|
||||
* {@linkplain #ALLOW_GAME game messages are blocked}.
|
||||
* Mods can use this to modify the message.
|
||||
* Use {@link #GAME} if not modifying the message.
|
||||
*
|
||||
* <p>Overlay is whether the message will be displayed in the action bar.
|
||||
* Use {@link #ALLOW_GAME to toggle overlay}.
|
||||
*/
|
||||
public static final Event<ModifyGame> MODIFY_GAME = EventFactory.createArrayBacked(ModifyGame.class, listeners -> (message, overlay) -> {
|
||||
for (ModifyGame listener : listeners) {
|
||||
message = listener.modifyReceivedGameMessage(message, overlay);
|
||||
}
|
||||
|
||||
return message;
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when the client receives a chat message,
|
||||
* which is any message sent by a player. Is not called when
|
||||
* {@linkplain #ALLOW_CHAT chat messages are blocked}.
|
||||
* Mods can use this to listen to the message.
|
||||
*
|
||||
* <p>If mods want to modify the message, they should use {@link #ALLOW_CHAT}
|
||||
* and manually add the new message to the chat hud using {@link ChatHud#addMessage(Text)}
|
||||
*/
|
||||
public static final Event<Chat> CHAT = EventFactory.createArrayBacked(Chat.class, listeners -> (message, signedMessage, sender, params, receptionTimestamp) -> {
|
||||
for (Chat listener : listeners) {
|
||||
listener.onReceiveChatMessage(message, signedMessage, sender, params, receptionTimestamp);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when the client receives a game message,
|
||||
* which is any message sent by the server. Is not called when
|
||||
* {@linkplain #ALLOW_GAME game messages are blocked}.
|
||||
* Mods can use this to listen to the message.
|
||||
*
|
||||
* <p>Overlay is whether the message will be displayed in the action bar.
|
||||
* Use {@link #ALLOW_GAME to toggle overlay}.
|
||||
*/
|
||||
public static final Event<Game> GAME = EventFactory.createArrayBacked(Game.class, listeners -> (message, overlay) -> {
|
||||
for (Game listener : listeners) {
|
||||
listener.onReceiveGameMessage(message, overlay);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when receiving a chat message is canceled with {@link #ALLOW_CHAT}.
|
||||
*/
|
||||
public static final Event<ChatCanceled> CHAT_CANCELED = EventFactory.createArrayBacked(ChatCanceled.class, listeners -> (message, signedMessage, sender, params, receptionTimestamp) -> {
|
||||
for (ChatCanceled listener : listeners) {
|
||||
listener.onReceiveChatMessageCanceled(message, signedMessage, sender, params, receptionTimestamp);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when receiving a game message is canceled with {@link #ALLOW_GAME}.
|
||||
*
|
||||
* <p>Overlay is whether the message would have been displayed in the action bar.
|
||||
*/
|
||||
public static final Event<GameCanceled> GAME_CANCELED = EventFactory.createArrayBacked(GameCanceled.class, listeners -> (message, overlay) -> {
|
||||
for (GameCanceled listener : listeners) {
|
||||
listener.onReceiveGameMessageCanceled(message, overlay);
|
||||
}
|
||||
});
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AllowChat {
|
||||
/**
|
||||
* Called when the client receives a chat message,
|
||||
* which is any message sent by a player.
|
||||
* Returning {@code false} prevents the message from being displayed, and
|
||||
* {@link #CHAT_CANCELED} will be triggered instead of {@link #CHAT}.
|
||||
*
|
||||
* @param message the message received from the server
|
||||
* @param signedMessage the signed message received from the server (nullable)
|
||||
* @param sender the sender of the message (nullable)
|
||||
* @param params the parameters of the message
|
||||
* @param receptionTimestamp the timestamp when the message was received
|
||||
* @return {@code true} if the message should be displayed, otherwise {@code false}
|
||||
*/
|
||||
boolean allowReceiveChatMessage(Text message, @Nullable SignedMessage signedMessage, @Nullable GameProfile sender, MessageType.Parameters params, Instant receptionTimestamp);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AllowGame {
|
||||
/**
|
||||
* Called when the client receives a game message,
|
||||
* which is any message sent by the server. Returning {@code false}
|
||||
* prevents the message from being displayed, and
|
||||
* {@link #GAME_CANCELED} will be triggered instead of {@link #MODIFY_GAME}.
|
||||
*
|
||||
* <p>Overlay is whether the message will be displayed in the action bar.
|
||||
* To toggle overlay, return false and call
|
||||
* {@link net.minecraft.client.network.ClientPlayerEntity#sendMessage(Text, boolean) ClientPlayerEntity.sendMessage(message, overlay)}.
|
||||
*
|
||||
* @param message the message received from the server
|
||||
* @param overlay whether the message will be displayed in the action bar
|
||||
* @return {@code true} if the message should be displayed, otherwise {@code false}
|
||||
*/
|
||||
boolean allowReceiveGameMessage(Text message, boolean overlay);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ModifyGame {
|
||||
/**
|
||||
* Called when the client receives a game message,
|
||||
* which is any message sent by the server. Is not called when
|
||||
* {@linkplain #ALLOW_GAME game messages are blocked}.
|
||||
* Use {@link #GAME} if not modifying the message.
|
||||
*
|
||||
* <p>Overlay is whether the message will be displayed in the action bar.
|
||||
* Use {@link #ALLOW_GAME} to toggle overlay.
|
||||
*
|
||||
* @param message the message received from the server
|
||||
* @param overlay whether the message will be displayed in the action bar
|
||||
* @return the modified message to display or the original {@code message} if the message is not modified
|
||||
*/
|
||||
Text modifyReceivedGameMessage(Text message, boolean overlay);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Chat {
|
||||
/**
|
||||
* Called when the client receives a chat message,
|
||||
* which is any message sent by a player. Is not called when
|
||||
* {@linkplain #ALLOW_CHAT chat messages are blocked}.
|
||||
*
|
||||
* @param message the message received from the server
|
||||
* @param signedMessage the signed message received from the server (nullable)
|
||||
* @param sender the sender of the message (nullable)
|
||||
* @param params the parameters of the message
|
||||
* @param receptionTimestamp the timestamp when the message was received
|
||||
*/
|
||||
void onReceiveChatMessage(Text message, @Nullable SignedMessage signedMessage, @Nullable GameProfile sender, MessageType.Parameters params, Instant receptionTimestamp);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Game {
|
||||
/**
|
||||
* Called when the client receives a game message,
|
||||
* which is any message sent by the server. Is not called when
|
||||
* {@linkplain #ALLOW_GAME game messages are blocked}.
|
||||
*
|
||||
* <p>Overlay is whether the message will be displayed in the action bar.
|
||||
* Use {@link #ALLOW_GAME} to toggle overlay.
|
||||
*
|
||||
* @param message the message received from the server
|
||||
* @param overlay whether the message will be displayed in the action bar
|
||||
*/
|
||||
void onReceiveGameMessage(Text message, boolean overlay);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ChatCanceled {
|
||||
/**
|
||||
* Called when receiving a chat message is canceled with {@link #ALLOW_CHAT}.
|
||||
*
|
||||
* @param message the message received from the server
|
||||
* @param signedMessage the signed message received from the server (nullable)
|
||||
* @param sender the sender of the message (nullable)
|
||||
* @param params the parameters of the message
|
||||
* @param receptionTimestamp the timestamp when the message was received
|
||||
*/
|
||||
void onReceiveChatMessageCanceled(Text message, @Nullable SignedMessage signedMessage, @Nullable GameProfile sender, MessageType.Parameters params, Instant receptionTimestamp);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface GameCanceled {
|
||||
/**
|
||||
* Called when receiving a game message is canceled with {@link #ALLOW_GAME}.
|
||||
*
|
||||
* @param message the message received from the server
|
||||
* @param overlay whether the message would have been displayed in the action bar
|
||||
*/
|
||||
void onReceiveGameMessageCanceled(Text message, boolean overlay);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.client.message.v1;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
|
||||
/**
|
||||
* Contains client-side events triggered when sending messages.
|
||||
*/
|
||||
public final class ClientSendMessageEvents {
|
||||
private ClientSendMessageEvents() {
|
||||
}
|
||||
|
||||
/**
|
||||
* An event triggered when the client is about to send a chat message,
|
||||
* typically from a client GUI. Mods can use this to block the message.
|
||||
*
|
||||
* <p>If a listener returned {@code false}, the message will not be sent,
|
||||
* the remaining listeners will not be called (if any), and
|
||||
* {@link #CHAT_CANCELED} will be triggered instead of {@link #MODIFY_CHAT}.
|
||||
*/
|
||||
public static final Event<AllowChat> ALLOW_CHAT = EventFactory.createArrayBacked(AllowChat.class, listeners -> (message) -> {
|
||||
for (AllowChat listener : listeners) {
|
||||
if (!listener.allowSendChatMessage(message)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when the client is about to send a command,
|
||||
* which is whenever the player executes a command
|
||||
* including client commands registered with {@code fabric-command-api}.
|
||||
* Mods can use this to block the message.
|
||||
* The command string does not include a slash at the beginning.
|
||||
*
|
||||
* <p>If a listener returned {@code false}, the command will not be sent,
|
||||
* the remaining listeners will not be called (if any), and
|
||||
* {@link #COMMAND_CANCELED} will be triggered instead of {@link #MODIFY_COMMAND}.
|
||||
*/
|
||||
public static final Event<AllowCommand> ALLOW_COMMAND = EventFactory.createArrayBacked(AllowCommand.class, listeners -> (command) -> {
|
||||
for (AllowCommand listener : listeners) {
|
||||
if (!listener.allowSendCommandMessage(command)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when the client sends a chat message,
|
||||
* typically from a client GUI. Is not called when {@linkplain
|
||||
* #ALLOW_CHAT chat messages are blocked}.
|
||||
* Mods can use this to modify the message.
|
||||
* Use {@link #CHAT} if not modifying the message.
|
||||
*/
|
||||
public static final Event<ModifyChat> MODIFY_CHAT = EventFactory.createArrayBacked(ModifyChat.class, listeners -> (message) -> {
|
||||
for (ModifyChat listener : listeners) {
|
||||
message = listener.modifySendChatMessage(message);
|
||||
}
|
||||
|
||||
return message;
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when the client sends a command,
|
||||
* which is whenever the player executes a command
|
||||
* including client commands registered with {@code fabric-command-api}.
|
||||
* Is not called when {@linkplain #ALLOW_COMMAND command messages are blocked}.
|
||||
* The command string does not include a slash at the beginning.
|
||||
* Mods can use this to modify the command.
|
||||
* Use {@link #COMMAND} if not modifying the command.
|
||||
*/
|
||||
public static final Event<ModifyCommand> MODIFY_COMMAND = EventFactory.createArrayBacked(ModifyCommand.class, listeners -> (command) -> {
|
||||
for (ModifyCommand listener : listeners) {
|
||||
command = listener.modifySendCommandMessage(command);
|
||||
}
|
||||
|
||||
return command;
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when the client sends a chat message,
|
||||
* typically from a client GUI. Is not called when {@linkplain
|
||||
* #ALLOW_CHAT chat messages are blocked}.
|
||||
* Mods can use this to listen to the message.
|
||||
*/
|
||||
public static final Event<Chat> CHAT = EventFactory.createArrayBacked(Chat.class, listeners -> (message) -> {
|
||||
for (Chat listener : listeners) {
|
||||
listener.onSendChatMessage(message);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when the client sends a command,
|
||||
* which is whenever the player executes a command
|
||||
* including client commands registered with {@code fabric-command-api}.
|
||||
* Is not called when {@linkplain #ALLOW_COMMAND command messages are blocked}.
|
||||
* The command string does not include a slash at the beginning.
|
||||
* Mods can use this to listen to the command.
|
||||
*/
|
||||
public static final Event<Command> COMMAND = EventFactory.createArrayBacked(Command.class, listeners -> (command) -> {
|
||||
for (Command listener : listeners) {
|
||||
listener.onSendCommandMessage(command);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when sending a chat message is canceled with {@link #ALLOW_CHAT}.
|
||||
*/
|
||||
public static final Event<ChatCanceled> CHAT_CANCELED = EventFactory.createArrayBacked(ChatCanceled.class, listeners -> (message) -> {
|
||||
for (ChatCanceled listener : listeners) {
|
||||
listener.onSendChatMessageCanceled(message);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event triggered when sending a command is canceled with {@link #ALLOW_COMMAND}.
|
||||
* The command string does not include a slash at the beginning.
|
||||
*/
|
||||
public static final Event<CommandCanceled> COMMAND_CANCELED = EventFactory.createArrayBacked(CommandCanceled.class, listeners -> (command) -> {
|
||||
for (CommandCanceled listener : listeners) {
|
||||
listener.onSendCommandMessageCanceled(command);
|
||||
}
|
||||
});
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AllowChat {
|
||||
/**
|
||||
* Called when the client is about to send a chat message,
|
||||
* typically from a client GUI. Returning {@code false}
|
||||
* prevents the message from being sent, and
|
||||
* {@link #CHAT_CANCELED} will be triggered instead of {@link #MODIFY_CHAT}.
|
||||
*
|
||||
* @param message the message that will be sent to the server
|
||||
* @return {@code true} if the message should be sent, otherwise {@code false}
|
||||
*/
|
||||
boolean allowSendChatMessage(String message);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AllowCommand {
|
||||
/**
|
||||
* Called when the client is about to send a command,
|
||||
* which is whenever the player executes a command
|
||||
* including client commands registered with {@code fabric-command-api}.
|
||||
* Returning {@code false} prevents the command from being sent, and
|
||||
* {@link #COMMAND_CANCELED} will be triggered instead of {@link #MODIFY_COMMAND}.
|
||||
* The command string does not include a slash at the beginning.
|
||||
*
|
||||
* @param command the command that will be sent to the server, without a slash at the beginning.
|
||||
* @return {@code true} if the command should be sent, otherwise {@code false}
|
||||
*/
|
||||
boolean allowSendCommandMessage(String command);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ModifyChat {
|
||||
/**
|
||||
* Called when the client sends a chat message,
|
||||
* typically from a client GUI. Is not called when {@linkplain
|
||||
* #ALLOW_CHAT chat messages are blocked}.
|
||||
* Use {@link #CHAT} if not modifying the message.
|
||||
*
|
||||
* @param message the message that will be sent to the server
|
||||
* @return the modified message that will be sent to the server
|
||||
*/
|
||||
String modifySendChatMessage(String message);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ModifyCommand {
|
||||
/**
|
||||
* Called when the client sends a command,
|
||||
* which is whenever the player executes a command
|
||||
* including client commands registered with {@code fabric-command-api}.
|
||||
* Is not called when {@linkplain #ALLOW_COMMAND command messages are blocked}.
|
||||
* The command string does not include a slash at the beginning.
|
||||
* Use {@link #COMMAND} if not modifying the command.
|
||||
*
|
||||
* @param command the command that will be sent to the server, without a slash at the beginning.
|
||||
* @return the modified command that will be sent to the server, without a slash at the beginning.
|
||||
*/
|
||||
String modifySendCommandMessage(String command);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Chat {
|
||||
/**
|
||||
* Called when the client sends a chat message,
|
||||
* typically from a client GUI. Is not called when {@linkplain
|
||||
* #ALLOW_CHAT chat messages are blocked}.
|
||||
*
|
||||
* @param message the message that will be sent to the server
|
||||
*/
|
||||
void onSendChatMessage(String message);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Command {
|
||||
/**
|
||||
* Called when the client sends a command,
|
||||
* which is whenever the player executes a command
|
||||
* including client commands registered with {@code fabric-command-api}.
|
||||
* Is not called when {@linkplain #ALLOW_COMMAND command messages are blocked}.
|
||||
* The command string does not include a slash at the beginning.
|
||||
*
|
||||
* @param command the command that will be sent to the server, without a slash at the beginning.
|
||||
*/
|
||||
void onSendCommandMessage(String command);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ChatCanceled {
|
||||
/**
|
||||
* Called when sending a chat message is canceled with {@link #ALLOW_CHAT}.
|
||||
*
|
||||
* @param message the message that is canceled from being sent to the server
|
||||
*/
|
||||
void onSendChatMessageCanceled(String message);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CommandCanceled {
|
||||
/**
|
||||
* Called when sending a command is canceled with {@link #ALLOW_COMMAND}.
|
||||
* The command string does not include a slash at the beginning.
|
||||
*
|
||||
* @param command the command that is being sent to the server, without a slash at the beginning.
|
||||
*/
|
||||
void onSendCommandMessageCanceled(String command);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.client.message;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
|
||||
import net.fabricmc.fabric.api.client.message.v1.ClientSendMessageEvents;
|
||||
|
||||
/**
|
||||
* Mixin to {@link ClientPlayNetworkHandler} to listen for sending messages and commands.
|
||||
* Priority set to 800 to inject before {@code fabric-command-api} so that this api will be called first.
|
||||
*/
|
||||
@Mixin(value = ClientPlayNetworkHandler.class, priority = 800)
|
||||
public abstract class ClientPlayNetworkHandlerMixin {
|
||||
@Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true)
|
||||
private void fabric_allowSendChatMessage(String content, CallbackInfo ci) {
|
||||
if (!ClientSendMessageEvents.ALLOW_CHAT.invoker().allowSendChatMessage(content)) {
|
||||
ClientSendMessageEvents.CHAT_CANCELED.invoker().onSendChatMessageCanceled(content);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "sendChatMessage", at = @At(value = "LOAD", ordinal = 0), ordinal = 0, argsOnly = true)
|
||||
private String fabric_modifySendChatMessage(String content) {
|
||||
content = ClientSendMessageEvents.MODIFY_CHAT.invoker().modifySendChatMessage(content);
|
||||
ClientSendMessageEvents.CHAT.invoker().onSendChatMessage(content);
|
||||
return content;
|
||||
}
|
||||
|
||||
@Inject(method = "sendChatCommand", at = @At("HEAD"), cancellable = true)
|
||||
private void fabric_allowSendCommandMessage(String command, CallbackInfo ci) {
|
||||
if (!ClientSendMessageEvents.ALLOW_COMMAND.invoker().allowSendCommandMessage(command)) {
|
||||
ClientSendMessageEvents.COMMAND_CANCELED.invoker().onSendCommandMessageCanceled(command);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "sendChatCommand", at = @At(value = "LOAD", ordinal = 0), ordinal = 0, argsOnly = true)
|
||||
private String fabric_modifySendCommandMessage(String command) {
|
||||
command = ClientSendMessageEvents.MODIFY_COMMAND.invoker().modifySendCommandMessage(command);
|
||||
ClientSendMessageEvents.COMMAND.invoker().onSendCommandMessage(command);
|
||||
return command;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.client.message;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.client.network.message.MessageHandler;
|
||||
import net.minecraft.network.message.MessageType;
|
||||
import net.minecraft.network.message.SignedMessage;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
|
||||
|
||||
@Mixin(MessageHandler.class)
|
||||
public abstract class MessageHandlerMixin {
|
||||
@Inject(method = "processChatMessageInternal", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;getChatHud()Lnet/minecraft/client/gui/hud/ChatHud;", ordinal = 0), cancellable = true)
|
||||
private void fabric_onSignedChatMessage(MessageType.Parameters params, SignedMessage message, Text decorated, GameProfile sender, boolean onlyShowSecureChat, Instant receptionTimestamp, CallbackInfoReturnable<Boolean> cir) {
|
||||
fabric_onChatMessage(decorated, message, sender, params, receptionTimestamp, cir);
|
||||
}
|
||||
|
||||
@Inject(method = "processChatMessageInternal", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;getChatHud()Lnet/minecraft/client/gui/hud/ChatHud;", ordinal = 1), cancellable = true)
|
||||
private void fabric_onFilteredSignedChatMessage(MessageType.Parameters params, SignedMessage message, Text decorated, GameProfile sender, boolean onlyShowSecureChat, Instant receptionTimestamp, CallbackInfoReturnable<Boolean> cir) {
|
||||
Text filtered = message.filterMask().getFilteredText(message.getSignedContent());
|
||||
|
||||
if (filtered != null) {
|
||||
fabric_onChatMessage(params.applyChatDecoration(filtered), message, sender, params, receptionTimestamp, cir);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "method_45745", at = @At("HEAD"), cancellable = true)
|
||||
private void fabric_onProfilelessChatMessage(MessageType.Parameters params, Text content, Instant receptionTimestamp, CallbackInfoReturnable<Boolean> cir) {
|
||||
fabric_onChatMessage(params.applyChatDecoration(content), null, null, params, receptionTimestamp, cir);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void fabric_onChatMessage(Text message, @Nullable SignedMessage signedMessage, @Nullable GameProfile sender, MessageType.Parameters params, Instant receptionTimestamp, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (ClientReceiveMessageEvents.ALLOW_CHAT.invoker().allowReceiveChatMessage(message, signedMessage, sender, params, receptionTimestamp)) {
|
||||
ClientReceiveMessageEvents.CHAT.invoker().onReceiveChatMessage(message, signedMessage, sender, params, receptionTimestamp);
|
||||
} else {
|
||||
ClientReceiveMessageEvents.CHAT_CANCELED.invoker().onReceiveChatMessageCanceled(message, signedMessage, sender, params, receptionTimestamp);
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onGameMessage", at = @At("HEAD"), cancellable = true)
|
||||
private void fabric_allowGameMessage(Text message, boolean overlay, CallbackInfo ci) {
|
||||
if (!ClientReceiveMessageEvents.ALLOW_GAME.invoker().allowReceiveGameMessage(message, overlay)) {
|
||||
ClientReceiveMessageEvents.GAME_CANCELED.invoker().onReceiveGameMessageCanceled(message, overlay);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "onGameMessage", at = @At(value = "LOAD", ordinal = 0), ordinal = 0, argsOnly = true)
|
||||
private Text fabric_modifyGameMessage(Text message, Text message1, boolean overlay) {
|
||||
message = ClientReceiveMessageEvents.MODIFY_GAME.invoker().modifyReceivedGameMessage(message, overlay);
|
||||
ClientReceiveMessageEvents.GAME.invoker().onReceiveGameMessage(message, overlay);
|
||||
return message;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "net.fabricmc.fabric.mixin.client.message",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"client": [
|
||||
"ClientPlayNetworkHandlerMixin",
|
||||
"MessageHandlerMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
|
@ -21,7 +21,11 @@
|
|||
},
|
||||
"description": "Adds message-related hooks.",
|
||||
"mixins": [
|
||||
"fabric-message-api-v1.mixins.json"
|
||||
"fabric-message-api-v1.mixins.json",
|
||||
{
|
||||
"config": "fabric-message-api-v1.client.mixins.json",
|
||||
"environment": "client"
|
||||
}
|
||||
],
|
||||
"custom": {
|
||||
"fabric-api:module-lifecycle": "experimental"
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.test.message;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
|
||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
|
||||
import net.fabricmc.fabric.api.client.message.v1.ClientSendMessageEvents;
|
||||
|
||||
public class ChatTestClient implements ClientModInitializer {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ChatTestClient.class);
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
//Register test client commands
|
||||
ClientCommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> dispatcher.register(ClientCommandManager.literal("block").then(ClientCommandManager.literal("send").executes(context -> {
|
||||
throw new AssertionError("This client command should be blocked!");
|
||||
}))));
|
||||
//Test client send message events
|
||||
ClientSendMessageEvents.ALLOW_CHAT.register((message) -> {
|
||||
if (message.contains("block send")) {
|
||||
LOGGER.info("Blocked chat message: " + message);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
ClientSendMessageEvents.MODIFY_CHAT.register((message) -> {
|
||||
if (message.contains("modify send")) {
|
||||
LOGGER.info("Modifying chat message: " + message);
|
||||
return "sending modified chat message";
|
||||
}
|
||||
|
||||
return message;
|
||||
});
|
||||
ClientSendMessageEvents.CHAT.register((message -> LOGGER.info("Sent chat message: " + message)));
|
||||
ClientSendMessageEvents.CHAT_CANCELED.register((message) -> LOGGER.info("Canceled sending chat message: " + message));
|
||||
//Test client send command events
|
||||
ClientSendMessageEvents.ALLOW_COMMAND.register((command) -> {
|
||||
if (command.contains("block send")) {
|
||||
LOGGER.info("Blocked command message: " + command);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
ClientSendMessageEvents.MODIFY_COMMAND.register((command) -> {
|
||||
if (command.contains("modify send")) {
|
||||
LOGGER.info("Modifying command message: " + command);
|
||||
return "sending modified command message";
|
||||
}
|
||||
|
||||
return command;
|
||||
});
|
||||
ClientSendMessageEvents.COMMAND.register((command -> LOGGER.info("Sent command message: " + command)));
|
||||
ClientSendMessageEvents.COMMAND_CANCELED.register((command) -> LOGGER.info("Canceled sending command message: " + command));
|
||||
//Test client receive message events
|
||||
ClientReceiveMessageEvents.ALLOW_CHAT.register((message, signedMessage, sender, params, receptionTimestamp) -> {
|
||||
if (message.getString().contains("block receive")) {
|
||||
LOGGER.info("Blocked receiving chat message: " + message.getString());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
ClientReceiveMessageEvents.CHAT.register((message, signedMessage, sender, params, receptionTimestamp) -> LOGGER.info("Received chat message sent by {} at time {}: {}", sender == null ? "null" : sender.getName(), receptionTimestamp.toEpochMilli(), message.getString()));
|
||||
ClientReceiveMessageEvents.CHAT_CANCELED.register((message, signedMessage, sender, params, receptionTimestamp) -> LOGGER.info("Cancelled receiving chat message sent by {} at time {}: {}", sender == null ? "null" : sender.getName(), receptionTimestamp.toEpochMilli(), message.getString()));
|
||||
//Test client receive game message events
|
||||
ClientReceiveMessageEvents.ALLOW_GAME.register((message, overlay) -> {
|
||||
if (message.getString().contains("block receive")) {
|
||||
LOGGER.info("Blocked receiving game message: " + message.getString());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
ClientReceiveMessageEvents.MODIFY_GAME.register((message, overlay) -> {
|
||||
if (message.getString().contains("modify receive")) {
|
||||
LOGGER.info("Modifying received game message: " + message.getString());
|
||||
return Text.of("modified receiving game message");
|
||||
}
|
||||
|
||||
return message;
|
||||
});
|
||||
ClientReceiveMessageEvents.GAME.register((message, overlay) -> LOGGER.info("Received game message with overlay {}: {}", overlay, message.getString()));
|
||||
ClientReceiveMessageEvents.GAME_CANCELED.register((message, overlay) -> LOGGER.info("Cancelled receiving game message with overlay {}: {}", overlay, message.getString()));
|
||||
}
|
||||
}
|
|
@ -6,11 +6,15 @@
|
|||
"environment": "*",
|
||||
"license": "Apache-2.0",
|
||||
"depends": {
|
||||
"fabric-message-api-v1": "*"
|
||||
"fabric-message-api-v1": "*",
|
||||
"fabric-command-api-v2": "*"
|
||||
},
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"net.fabricmc.fabric.test.message.ChatTest"
|
||||
],
|
||||
"client": [
|
||||
"net.fabricmc.fabric.test.message.ChatTestClient"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue