mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-14 19:25:23 -05:00
Message API: 1.19.1 changes (#2411)
* BREAKING: Add server param to game message events * Update javadocs * Update testmod * Fix param name in testmod * Update ServerMessageEvents.java
This commit is contained in:
parent
c558657297
commit
e6c0642c7f
4 changed files with 50 additions and 28 deletions
|
@ -41,10 +41,12 @@ import net.fabricmc.fabric.api.event.EventFactory;
|
|||
* function. If not given, the message decorator will run in the default phase, which is between
|
||||
* the content phase and the styling phase.
|
||||
*
|
||||
* <p>When implementing a message decorator, it is <strong>very important that the decorator be
|
||||
* pure; i.e. return the same text when called multiple times for the same arguments (message and
|
||||
* sender)</strong> - otherwise the server detects a mismatch between the preview and the actual message,
|
||||
* and discards the message because it was improperly signed.
|
||||
* <p>The message decorator's result is cached (as of 1.19.1) if the chat preview is enabled.
|
||||
* If the original message did not change between the last preview and submission, the decorator
|
||||
* is not called during submission and the cached preview is used instead. Note that the
|
||||
* decorator can still be called during submission if the chat preview is disabled, the
|
||||
* sent message was not the same as the previewed message, or if text filtering was enabled and
|
||||
* it produced a different message.
|
||||
*
|
||||
* <p>Example of registering a content phase message decorator:
|
||||
*
|
||||
|
|
|
@ -18,6 +18,7 @@ package net.fabricmc.fabric.api.message.v1;
|
|||
|
||||
import net.minecraft.network.message.MessageType;
|
||||
import net.minecraft.network.message.SignedMessage;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.filter.FilteredMessage;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
@ -40,9 +41,9 @@ public final class ServerMessageEvents {
|
|||
* only if {@link #ALLOW_COMMAND_MESSAGE} event did not block the message,
|
||||
* and after triggering {@link #COMMAND_MESSAGE} event.
|
||||
*/
|
||||
public static final Event<AllowChatMessage> ALLOW_CHAT_MESSAGE = EventFactory.createArrayBacked(AllowChatMessage.class, handlers -> (message, sender, typeKey) -> {
|
||||
public static final Event<AllowChatMessage> ALLOW_CHAT_MESSAGE = EventFactory.createArrayBacked(AllowChatMessage.class, handlers -> (message, sender, params) -> {
|
||||
for (AllowChatMessage handler : handlers) {
|
||||
if (!handler.allowChatMessage(message, sender, typeKey)) return false;
|
||||
if (!handler.allowChatMessage(message, sender, params)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -57,9 +58,9 @@ public final class ServerMessageEvents {
|
|||
* the remaining listeners will not be called (if any), and {@link #GAME_MESSAGE}
|
||||
* event will not be triggered.
|
||||
*/
|
||||
public static final Event<AllowGameMessage> ALLOW_GAME_MESSAGE = EventFactory.createArrayBacked(AllowGameMessage.class, handlers -> (message, typeKey) -> {
|
||||
public static final Event<AllowGameMessage> ALLOW_GAME_MESSAGE = EventFactory.createArrayBacked(AllowGameMessage.class, handlers -> (server, message, overlay) -> {
|
||||
for (AllowGameMessage handler : handlers) {
|
||||
if (!handler.allowGameMessage(message, typeKey)) return false;
|
||||
if (!handler.allowGameMessage(server, message, overlay)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -78,9 +79,9 @@ public final class ServerMessageEvents {
|
|||
* {@link #ALLOW_CHAT_MESSAGE} and {@link #CHAT_MESSAGE} events will also be
|
||||
* triggered after triggering {@link #COMMAND_MESSAGE}.
|
||||
*/
|
||||
public static final Event<AllowCommandMessage> ALLOW_COMMAND_MESSAGE = EventFactory.createArrayBacked(AllowCommandMessage.class, handlers -> (message, source, typeKey) -> {
|
||||
public static final Event<AllowCommandMessage> ALLOW_COMMAND_MESSAGE = EventFactory.createArrayBacked(AllowCommandMessage.class, handlers -> (message, source, params) -> {
|
||||
for (AllowCommandMessage handler : handlers) {
|
||||
if (!handler.allowCommandMessage(message, source, typeKey)) return false;
|
||||
if (!handler.allowCommandMessage(message, source, params)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -95,9 +96,9 @@ public final class ServerMessageEvents {
|
|||
* only if {@link #ALLOW_COMMAND_MESSAGE} event did not block the message,
|
||||
* and after triggering {@link #COMMAND_MESSAGE} event.
|
||||
*/
|
||||
public static final Event<ChatMessage> CHAT_MESSAGE = EventFactory.createArrayBacked(ChatMessage.class, handlers -> (message, sender, typeKey) -> {
|
||||
public static final Event<ChatMessage> CHAT_MESSAGE = EventFactory.createArrayBacked(ChatMessage.class, handlers -> (message, sender, params) -> {
|
||||
for (ChatMessage handler : handlers) {
|
||||
handler.onChatMessage(message, sender, typeKey);
|
||||
handler.onChatMessage(message, sender, params);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -106,9 +107,9 @@ public final class ServerMessageEvents {
|
|||
* include death messages, join/leave messages, and advancement messages. Is not called
|
||||
* when {@linkplain #ALLOW_GAME_MESSAGE game messages are blocked}.
|
||||
*/
|
||||
public static final Event<GameMessage> GAME_MESSAGE = EventFactory.createArrayBacked(GameMessage.class, handlers -> (message, typeKey) -> {
|
||||
public static final Event<GameMessage> GAME_MESSAGE = EventFactory.createArrayBacked(GameMessage.class, handlers -> (server, message, overlay) -> {
|
||||
for (GameMessage handler : handlers) {
|
||||
handler.onGameMessage(message, typeKey);
|
||||
handler.onGameMessage(server, message, overlay);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -120,9 +121,9 @@ public final class ServerMessageEvents {
|
|||
* <p>If the command is executed by a player, {@link #ALLOW_CHAT_MESSAGE} and
|
||||
* {@link #CHAT_MESSAGE} events will also be triggered after this event.
|
||||
*/
|
||||
public static final Event<CommandMessage> COMMAND_MESSAGE = EventFactory.createArrayBacked(CommandMessage.class, handlers -> (message, source, typeKey) -> {
|
||||
public static final Event<CommandMessage> COMMAND_MESSAGE = EventFactory.createArrayBacked(CommandMessage.class, handlers -> (message, source, params) -> {
|
||||
for (CommandMessage handler : handlers) {
|
||||
handler.onCommandMessage(message, source, typeKey);
|
||||
handler.onCommandMessage(message, source, params);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -157,11 +158,12 @@ public final class ServerMessageEvents {
|
|||
* prevents the message from being broadcast and the {@link #GAME_MESSAGE} event
|
||||
* from triggering.
|
||||
*
|
||||
* @param server the server that sent the message
|
||||
* @param message the broadcast message; use {@code message.raw().getContent()} to get the text
|
||||
* @param overlay true when the message is an overlay
|
||||
* @param overlay {@code true} when the message is an overlay
|
||||
* @return {@code true} if the message should be broadcast, otherwise {@code false}
|
||||
*/
|
||||
boolean allowGameMessage(Text message, boolean overlay);
|
||||
boolean allowGameMessage(MinecraftServer server, Text message, boolean overlay);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
|
@ -209,10 +211,11 @@ public final class ServerMessageEvents {
|
|||
* include death messages, join/leave messages, and advancement messages. Is not called
|
||||
* when {@linkplain #ALLOW_GAME_MESSAGE game messages are blocked}.
|
||||
*
|
||||
* @param server the server that sent the message
|
||||
* @param message the broadcast message; use {@code message.raw().getContent()} to get the text
|
||||
* @param overlay true when the message is an overlay
|
||||
* @param overlay {@code true} when the message is an overlay
|
||||
*/
|
||||
void onGameMessage(Text message, boolean overlay);
|
||||
void onGameMessage(MinecraftServer server, Text message, boolean overlay);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
|
|
|
@ -18,13 +18,16 @@ package net.fabricmc.fabric.mixin.message;
|
|||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import net.minecraft.network.message.MessageType;
|
||||
import net.minecraft.network.message.SignedMessage;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.PlayerManager;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.filter.FilteredMessage;
|
||||
|
@ -35,6 +38,10 @@ import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
|
|||
|
||||
@Mixin(PlayerManager.class)
|
||||
public class PlayerManagerMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private MinecraftServer server;
|
||||
|
||||
@Inject(method = "broadcast(Lnet/minecraft/server/filter/FilteredMessage;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/network/message/MessageType$Parameters;)V", at = @At("HEAD"), cancellable = true)
|
||||
private void onSendChatMessage(FilteredMessage<SignedMessage> message, ServerPlayerEntity sender, MessageType.Parameters params, CallbackInfo ci) {
|
||||
if (!ServerMessageEvents.ALLOW_CHAT_MESSAGE.invoker().allowChatMessage(message, sender, params)) {
|
||||
|
@ -47,12 +54,12 @@ public class PlayerManagerMixin {
|
|||
|
||||
@Inject(method = "broadcast(Lnet/minecraft/text/Text;Ljava/util/function/Function;Z)V", at = @At("HEAD"), cancellable = true)
|
||||
private void onSendGameMessage(Text message, Function<ServerPlayerEntity, Text> playerMessageFactory, boolean overlay, CallbackInfo ci) {
|
||||
if (!ServerMessageEvents.ALLOW_GAME_MESSAGE.invoker().allowGameMessage(message, overlay)) {
|
||||
if (!ServerMessageEvents.ALLOW_GAME_MESSAGE.invoker().allowGameMessage(this.server, message, overlay)) {
|
||||
ci.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
ServerMessageEvents.GAME_MESSAGE.invoker().onGameMessage(message, overlay);
|
||||
ServerMessageEvents.GAME_MESSAGE.invoker().onGameMessage(this.server, message, overlay);
|
||||
}
|
||||
|
||||
@Inject(method = "broadcast(Lnet/minecraft/server/filter/FilteredMessage;Lnet/minecraft/server/command/ServerCommandSource;Lnet/minecraft/network/message/MessageType$Parameters;)V", at = @At("HEAD"), cancellable = true)
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.concurrent.Executor;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableTextContent;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
|
@ -46,6 +47,15 @@ public class ChatTest implements ModInitializer {
|
|||
return CompletableFuture.completedFuture(message);
|
||||
});
|
||||
|
||||
// Content phase testing, with variable info
|
||||
ServerMessageDecoratorEvent.EVENT.register(ServerMessageDecoratorEvent.CONTENT_PHASE, (sender, message) -> {
|
||||
if (message.getString().contains("random")) {
|
||||
return CompletableFuture.completedFuture(Text.of(String.valueOf(Random.create().nextBetween(0, 100))));
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(message);
|
||||
});
|
||||
|
||||
// Basic styling phase testing
|
||||
ServerMessageDecoratorEvent.EVENT.register(ServerMessageDecoratorEvent.STYLING_PHASE, (sender, message) -> {
|
||||
if (sender != null && sender.getAbilities().creativeMode) {
|
||||
|
@ -74,20 +84,20 @@ public class ChatTest implements ModInitializer {
|
|||
|
||||
// ServerMessageEvents
|
||||
ServerMessageEvents.CHAT_MESSAGE.register(
|
||||
(message, sender, typeKey) -> LOGGER.info("ChatTest: {} sent \"{}\"", sender, message)
|
||||
(message, sender, params) -> LOGGER.info("ChatTest: {} sent \"{}\"", sender, message)
|
||||
);
|
||||
ServerMessageEvents.GAME_MESSAGE.register(
|
||||
(message, typeKey) -> LOGGER.info("ChatTest: server sent \"{}\"", message)
|
||||
(server, message, overlay) -> LOGGER.info("ChatTest: server sent \"{}\"", message)
|
||||
);
|
||||
ServerMessageEvents.COMMAND_MESSAGE.register(
|
||||
(message, source, typeKey) -> LOGGER.info("ChatTest: command sent \"{}\"", message)
|
||||
(message, source, params) -> LOGGER.info("ChatTest: command sent \"{}\"", message)
|
||||
);
|
||||
|
||||
// ServerMessageEvents blocking
|
||||
ServerMessageEvents.ALLOW_CHAT_MESSAGE.register(
|
||||
(message, sender, typeKey) -> !message.raw().getContent().getString().contains("sadtater")
|
||||
(message, sender, params) -> !message.raw().getContent().getString().contains("sadtater")
|
||||
);
|
||||
ServerMessageEvents.ALLOW_GAME_MESSAGE.register((message, typeKey) -> {
|
||||
ServerMessageEvents.ALLOW_GAME_MESSAGE.register((server, message, overlay) -> {
|
||||
if (message.getContent() instanceof TranslatableTextContent translatable) {
|
||||
return !translatable.getKey().startsWith("death.attack.badRespawnPoint.");
|
||||
}
|
||||
|
@ -95,7 +105,7 @@ public class ChatTest implements ModInitializer {
|
|||
return true;
|
||||
});
|
||||
ServerMessageEvents.ALLOW_COMMAND_MESSAGE.register(
|
||||
(message, source, typeKey) -> !message.raw().getContent().getString().contains("sadtater")
|
||||
(message, source, params) -> !message.raw().getContent().getString().contains("sadtater")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue