net.minecraft.network.chat

This commit is contained in:
Noah van der Aa 2024-12-14 18:44:07 +01:00
parent 52d26db5a0
commit 02fb33c3ee
No known key found for this signature in database
GPG key ID: 547D90BC6FF753CF
13 changed files with 156 additions and 159 deletions

View file

@ -0,0 +1,20 @@
--- a/net/minecraft/network/chat/ChatDecorator.java
+++ b/net/minecraft/network/chat/ChatDecorator.java
@@ -5,7 +_,14 @@
@FunctionalInterface
public interface ChatDecorator {
- ChatDecorator PLAIN = (player, message) -> message;
-
- Component decorate(@Nullable ServerPlayer player, Component message);
+ ChatDecorator PLAIN = (sender, message) -> java.util.concurrent.CompletableFuture.completedFuture(message); // Paper - adventure; support async chat decoration events
+
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - adventure; support chat decoration events (callers should use the overload with CommandSourceStack)
+ java.util.concurrent.CompletableFuture<Component> decorate(@Nullable ServerPlayer sender, Component message); // Paper - adventure; support async chat decoration events
+
+ // Paper start - adventure; support async chat decoration events
+ default java.util.concurrent.CompletableFuture<Component> decorate(@Nullable ServerPlayer sender, @Nullable net.minecraft.commands.CommandSourceStack commandSourceStack, Component message) {
+ throw new UnsupportedOperationException("Must override this implementation");
+ }
+ // Paper end - adventure; support async chat decoration events
}

View file

@ -1,23 +1,19 @@
--- a/net/minecraft/network/chat/Component.java
+++ b/net/minecraft/network/chat/Component.java
@@ -37,9 +37,23 @@
import net.minecraft.resources.ResourceLocation;
@@ -37,7 +_,19 @@
import net.minecraft.util.FormattedCharSequence;
import net.minecraft.world.level.ChunkPos;
+// CraftBukkit start
+import java.util.stream.Stream;
+// CraftBukkit end
-public interface Component extends Message, FormattedText {
+public interface Component extends Message, FormattedText, Iterable<Component> { // CraftBukkit
+
+ // CraftBukkit start
+ default Stream<Component> stream() {
+ return com.google.common.collect.Streams.concat(new Stream[]{Stream.of(this), this.getSiblings().stream().flatMap(Component::stream)});
+ default java.util.stream.Stream<Component> stream() {
+ return com.google.common.collect.Streams.concat(new java.util.stream.Stream[]{java.util.stream.Stream.of(this), this.getSiblings().stream().flatMap(Component::stream)});
+ }
+
+ @Override
+ default Iterator<Component> iterator() {
+ default java.util.Iterator<Component> iterator() {
+ return this.stream().iterator();
+ }
+ // CraftBukkit end

View file

@ -1,6 +1,6 @@
--- a/net/minecraft/network/chat/ComponentSerialization.java
+++ b/net/minecraft/network/chat/ComponentSerialization.java
@@ -37,9 +37,31 @@
@@ -37,9 +_,31 @@
public class ComponentSerialization {
public static final Codec<Component> CODEC = Codec.recursive("Component", ComponentSerialization::createCodec);
@ -34,8 +34,8 @@
public static final StreamCodec<RegistryFriendlyByteBuf, Optional<Component>> TRUSTED_OPTIONAL_STREAM_CODEC = TRUSTED_STREAM_CODEC.apply(
ByteBufCodecs::optional
);
@@ -100,7 +122,27 @@
return ExtraCodecs.orCompressed(mapCodec3, mapCodec2);
@@ -102,7 +_,25 @@
return ExtraCodecs.orCompressed(mapCodec2, mapCodec1);
}
+ // Paper start - adventure; create separate codec for each locale
@ -48,23 +48,21 @@
+ return LOCALIZED_CODECS.computeIfAbsent(locale,
+ loc -> Codec.recursive("Component", selfCodec -> createCodec(selfCodec, loc)));
+ }
+
+
+ // Paper end - adventure; create separate codec for each locale
+
private static Codec<Component> createCodec(Codec<Component> selfCodec) {
private static Codec<Component> createCodec(Codec<Component> codec) {
+ // Paper start - adventure; create separate codec for each locale
+ return createCodec(selfCodec, null);
+ return createCodec(codec, null);
+ }
+
+ private static Codec<Component> createCodec(Codec<Component> selfCodec, @javax.annotation.Nullable java.util.Locale locale) {
+ private static Codec<Component> createCodec(Codec<Component> codec, @javax.annotation.Nullable java.util.Locale locale) {
+ // Paper end - adventure; create separate codec for each locale
ComponentContents.Type<?>[] types = new ComponentContents.Type[]{
PlainTextContents.TYPE, TranslatableContents.TYPE, KeybindContents.TYPE, ScoreContents.TYPE, SelectorContents.TYPE, NbtContents.TYPE
};
@@ -113,6 +155,34 @@
)
.apply(instance, MutableComponent::new)
@@ -115,6 +_,34 @@
)
.apply(instance, MutableComponent::new)
);
+ // Paper start - adventure; create separate codec for each locale
+ final Codec<Component> origCodec = codec;
@ -94,6 +92,6 @@
+ }
+ };
+ // Paper end - adventure; create separate codec for each locale
return Codec.either(Codec.either(Codec.STRING, ExtraCodecs.nonEmptyList(selfCodec.listOf())), codec)
.xmap(either -> either.map(either2 -> either2.map(Component::literal, ComponentSerialization::createFromList), text -> (Component)text), text -> {
String string = text.tryCollapseToString();
return Codec.either(Codec.either(Codec.STRING, ExtraCodecs.nonEmptyList(codec.listOf())), codec1)
.xmap(
either -> either.map(either1 -> either1.map(Component::literal, ComponentSerialization::createFromList), component -> (Component)component),

View file

@ -1,12 +1,15 @@
--- a/net/minecraft/network/chat/ComponentUtils.java
+++ b/net/minecraft/network/chat/ComponentUtils.java
@@ -33,14 +33,39 @@
@@ -33,6 +_,7 @@
}
}
+ @io.papermc.paper.annotation.DoNotUse // Paper - validate separators - right now this method is only used for separator evaluation. Error on build if this changes to re-evaluate.
public static Optional<MutableComponent> updateForEntity(@Nullable CommandSourceStack source, Optional<Component> text, @Nullable Entity sender, int depth) throws CommandSyntaxException {
return text.isPresent() ? Optional.of(updateForEntity(source, text.get(), sender, depth)) : Optional.empty();
public static Optional<MutableComponent> updateForEntity(
@Nullable CommandSourceStack commandSourceStack, Optional<Component> optionalComponent, @Nullable Entity entity, int recursionDepth
) throws CommandSyntaxException {
@@ -41,12 +_,40 @@
: Optional.empty();
}
+ // Paper start - validate separator
@ -14,13 +17,16 @@
+ if (text.isEmpty() || !isValidSelector(text.get())) return Optional.empty();
+ return Optional.of(updateForEntity(source, text.get(), sender, depth));
+ }
+
+ public static boolean isValidSelector(final Component component) {
+ final ComponentContents contents = component.getContents();
+
+ if (contents instanceof net.minecraft.network.chat.contents.NbtContents || contents instanceof net.minecraft.network.chat.contents.SelectorContents) return false;
+ if (contents instanceof net.minecraft.network.chat.contents.NbtContents || contents instanceof net.minecraft.network.chat.contents.SelectorContents)
+ return false;
+ if (contents instanceof final net.minecraft.network.chat.contents.TranslatableContents translatableContents) {
+ for (final Object arg : translatableContents.getArgs()) {
+ if (arg instanceof final Component argumentAsComponent && !isValidSelector(argumentAsComponent)) return false;
+ if (arg instanceof final Component argumentAsComponent && !isValidSelector(argumentAsComponent))
+ return false;
+ }
+ }
+
@ -28,15 +34,18 @@
+ }
+ // Paper end - validate separator
+
public static MutableComponent updateForEntity(@Nullable CommandSourceStack source, Component text, @Nullable Entity sender, int depth) throws CommandSyntaxException {
if (depth > 100) {
return text.copy();
public static MutableComponent updateForEntity(
@Nullable CommandSourceStack commandSourceStack, Component component, @Nullable Entity entity, int recursionDepth
) throws CommandSyntaxException {
if (recursionDepth > 100) {
return component.copy();
} else {
+ // Paper start - adventure; pass actual vanilla component
+ if (text instanceof io.papermc.paper.adventure.AdventureComponent adventureComponent) {
+ text = adventureComponent.deepConverted();
+ if (component instanceof io.papermc.paper.adventure.AdventureComponent adventureComponent) {
+ component = adventureComponent.deepConverted();
+ }
+ // Paper end - adventure; pass actual vanilla component
MutableComponent mutableComponent = text.getContents().resolve(source, sender, depth + 1);
+
MutableComponent mutableComponent = component.getContents().resolve(commandSourceStack, entity, recursionDepth + 1);
for (Component component : text.getSiblings()) {
for (Component component1 : component.getSiblings()) {

View file

@ -1,6 +1,6 @@
--- a/net/minecraft/network/chat/MessageSignature.java
+++ b/net/minecraft/network/chat/MessageSignature.java
@@ -13,6 +13,7 @@
@@ -13,6 +_,7 @@
import net.minecraft.util.SignatureValidator;
public record MessageSignature(byte[] bytes) {

View file

@ -1,14 +1,14 @@
--- a/net/minecraft/network/chat/MutableComponent.java
+++ b/net/minecraft/network/chat/MutableComponent.java
@@ -94,6 +94,11 @@
@@ -94,6 +_,11 @@
@Override
public boolean equals(Object object) {
public boolean equals(Object other) {
+ // Paper start - make AdventureComponent equivalent
+ if (object instanceof io.papermc.paper.adventure.AdventureComponent adventureComponent) {
+ object = adventureComponent.deepConverted();
+ if (other instanceof io.papermc.paper.adventure.AdventureComponent adventureComponent) {
+ other = adventureComponent.deepConverted();
+ }
+ // Paper end - make AdventureComponent equivalent
return this == object
|| object instanceof MutableComponent mutableComponent
return this == other
|| other instanceof MutableComponent mutableComponent
&& this.contents.equals(mutableComponent.contents)

View file

@ -0,0 +1,43 @@
--- a/net/minecraft/network/chat/OutgoingChatMessage.java
+++ b/net/minecraft/network/chat/OutgoingChatMessage.java
@@ -7,6 +_,12 @@
void sendToPlayer(ServerPlayer player, boolean filtered, ChatType.Bound boundType);
+ // Paper start
+ default void sendToPlayer(ServerPlayer sender, boolean filterMaskEnabled, ChatType.Bound params, @javax.annotation.Nullable Component unsigned) {
+ this.sendToPlayer(sender, filterMaskEnabled, params);
+ }
+ // Paper end
+
static OutgoingChatMessage create(PlayerChatMessage message) {
return (OutgoingChatMessage)(message.isSystem()
? new OutgoingChatMessage.Disguised(message.decoratedContent())
@@ -16,7 +_,12 @@
public record Disguised(@Override Component content) implements OutgoingChatMessage {
@Override
public void sendToPlayer(ServerPlayer player, boolean filtered, ChatType.Bound boundType) {
- player.connection.sendDisguisedChatMessage(this.content, boundType);
+ // Paper start
+ this.sendToPlayer(player, filtered, boundType, null);
+ }
+ public void sendToPlayer(ServerPlayer player, boolean filtered, ChatType.Bound boundType, @javax.annotation.Nullable Component unsigned) {
+ player.connection.sendDisguisedChatMessage(unsigned != null ? unsigned : this.content, boundType);
+ // Paper end
}
}
@@ -28,7 +_,13 @@
@Override
public void sendToPlayer(ServerPlayer player, boolean filtered, ChatType.Bound boundType) {
+ // Paper start
+ this.sendToPlayer(player, filtered, boundType, null);
+ }
+ public void sendToPlayer(ServerPlayer player, boolean filtered, ChatType.Bound boundType, @javax.annotation.Nullable Component unsigned) {
+ // Paper end
PlayerChatMessage playerChatMessage = this.message.filter(filtered);
+ playerChatMessage = unsigned != null ? playerChatMessage.withUnsignedContent(unsigned) : playerChatMessage; // Paper
if (!playerChatMessage.isFullyFiltered()) {
player.connection.sendPlayerChatMessage(playerChatMessage, boundType);
}

View file

@ -1,6 +1,6 @@
--- a/net/minecraft/network/chat/PlayerChatMessage.java
+++ b/net/minecraft/network/chat/PlayerChatMessage.java
@@ -17,6 +17,42 @@
@@ -17,6 +_,43 @@
public record PlayerChatMessage(
SignedMessageLink link, @Nullable MessageSignature signature, SignedMessageBody signedBody, @Nullable Component unsignedContent, FilterMask filterMask
) {
@ -40,14 +40,15 @@
+ return new AdventureView();
+ }
+ // Paper end - adventure; support signed messages
+
public static final MapCodec<PlayerChatMessage> MAP_CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
SignedMessageLink.CODEC.fieldOf("link").forGetter(PlayerChatMessage::link),
@@ -47,7 +83,14 @@
SignedMessageLink.CODEC.fieldOf("link").forGetter(PlayerChatMessage::link),
@@ -47,7 +_,14 @@
}
public PlayerChatMessage withUnsignedContent(Component unsignedContent) {
- Component component = !unsignedContent.equals(Component.literal(this.signedContent())) ? unsignedContent : null;
public PlayerChatMessage withUnsignedContent(Component message) {
- Component component = !message.equals(Component.literal(this.signedContent())) ? message : null;
+ // Paper start - adventure
+ final Component component;
+ if (unsignedContent instanceof io.papermc.paper.adventure.AdventureComponent advComponent) {

View file

@ -1,9 +1,9 @@
--- a/net/minecraft/network/chat/SignedMessageChain.java
+++ b/net/minecraft/network/chat/SignedMessageChain.java
@@ -40,14 +40,14 @@
@@ -40,14 +_,14 @@
if (signature == null) {
throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.MISSING_PROFILE_KEY);
} else if (playerPublicKey.data().hasExpired()) {
} else if (publicKey.data().hasExpired()) {
- throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.EXPIRED_PROFILE_KEY);
+ throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.EXPIRED_PROFILE_KEY, org.bukkit.event.player.PlayerKickEvent.Cause.EXPIRED_PROFILE_PUBLIC_KEY); // Paper - kick event causes
} else {
@ -17,21 +17,21 @@
} else {
SignedMessageChain.this.lastTimeStamp = body.timeStamp();
PlayerChatMessage playerChatMessage = new PlayerChatMessage(signedMessageLink, signature, body, null, FilterMask.PASS_THROUGH);
@@ -80,9 +80,16 @@
@@ -80,8 +_,15 @@
static final Component INVALID_SIGNATURE = Component.translatable("chat.disabled.invalid_signature");
static final Component OUT_OF_ORDER_CHAT = Component.translatable("chat.disabled.out_of_order_chat");
- public DecodeException(Component message) {
- public DecodeException(Component component) {
- super(component);
+ // Paper start
+ public final org.bukkit.event.player.PlayerKickEvent.Cause kickCause;
+ public DecodeException(Component message, org.bukkit.event.player.PlayerKickEvent.Cause event) {
super(message);
+ super(message);
+ this.kickCause = event;
}
+ }
+ // Paper end
+ public DecodeException(Component message) {
+ this(message, org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); // Paper
+ }
}
}
@FunctionalInterface

View file

@ -0,0 +1,34 @@
--- a/net/minecraft/network/chat/TextColor.java
+++ b/net/minecraft/network/chat/TextColor.java
@@ -17,23 +_,29 @@
public static final Codec<TextColor> CODEC = Codec.STRING.comapFlatMap(TextColor::parseColor, TextColor::serialize);
private static final Map<ChatFormatting, TextColor> LEGACY_FORMAT_TO_COLOR = Stream.of(ChatFormatting.values())
.filter(ChatFormatting::isColor)
- .collect(ImmutableMap.toImmutableMap(Function.identity(), formatting -> new TextColor(formatting.getColor(), formatting.getName())));
+ .collect(ImmutableMap.toImmutableMap(Function.identity(), formatting -> new TextColor(formatting.getColor(), formatting.getName(), formatting))); // CraftBukkit
private static final Map<String, TextColor> NAMED_COLORS = LEGACY_FORMAT_TO_COLOR.values()
.stream()
.collect(ImmutableMap.toImmutableMap(textColor -> textColor.name, Function.identity()));
private final int value;
@Nullable
public final String name;
+ // CraftBukkit start
+ @Nullable
+ public final ChatFormatting format;
- private TextColor(int value, String name) {
+ private TextColor(int value, String name, ChatFormatting format) {
this.value = value & 16777215;
this.name = name;
+ this.format = format;
}
private TextColor(int value) {
this.value = value & 16777215;
this.name = null;
+ this.format = null;
}
+ // CraftBukkit end
public int getValue() {
return this.value;

View file

@ -1,23 +0,0 @@
--- a/net/minecraft/network/chat/ChatDecorator.java
+++ b/net/minecraft/network/chat/ChatDecorator.java
@@ -2,10 +2,18 @@
import javax.annotation.Nullable;
import net.minecraft.server.level.ServerPlayer;
+import java.util.concurrent.CompletableFuture; // Paper
@FunctionalInterface
public interface ChatDecorator {
- ChatDecorator PLAIN = (sender, message) -> message;
+ ChatDecorator PLAIN = (sender, message) -> CompletableFuture.completedFuture(message); // Paper - adventure; support async chat decoration events
- Component decorate(@Nullable ServerPlayer sender, Component message);
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - adventure; support chat decoration events (callers should use the overload with CommandSourceStack)
+ CompletableFuture<Component> decorate(@Nullable ServerPlayer sender, Component message); // Paper - adventure; support async chat decoration events
+
+ // Paper start - adventure; support async chat decoration events
+ default CompletableFuture<Component> decorate(@Nullable ServerPlayer sender, @Nullable net.minecraft.commands.CommandSourceStack commandSourceStack, Component message) {
+ throw new UnsupportedOperationException("Must override this implementation");
+ }
+ // Paper end - adventure; support async chat decoration events
}

View file

@ -1,44 +0,0 @@
--- a/net/minecraft/network/chat/OutgoingChatMessage.java
+++ b/net/minecraft/network/chat/OutgoingChatMessage.java
@@ -7,6 +7,12 @@
void sendToPlayer(ServerPlayer sender, boolean filterMaskEnabled, ChatType.Bound params);
+ // Paper start
+ default void sendToPlayer(ServerPlayer sender, boolean filterMaskEnabled, ChatType.Bound params, @javax.annotation.Nullable Component unsigned) {
+ this.sendToPlayer(sender, filterMaskEnabled, params);
+ }
+ // Paper end
+
static OutgoingChatMessage create(PlayerChatMessage message) {
return (OutgoingChatMessage)(message.isSystem()
? new OutgoingChatMessage.Disguised(message.decoratedContent())
@@ -16,8 +22,13 @@
public static record Disguised(@Override Component content) implements OutgoingChatMessage {
@Override
public void sendToPlayer(ServerPlayer sender, boolean filterMaskEnabled, ChatType.Bound params) {
- sender.connection.sendDisguisedChatMessage(this.content, params);
+ // Paper start
+ this.sendToPlayer(sender, filterMaskEnabled, params, null);
}
+ public void sendToPlayer(ServerPlayer sender, boolean filterMaskEnabled, ChatType.Bound params, @javax.annotation.Nullable Component unsigned) {
+ sender.connection.sendDisguisedChatMessage(unsigned != null ? unsigned : this.content, params);
+ // Paper end
+ }
}
public static record Player(PlayerChatMessage message) implements OutgoingChatMessage {
@@ -28,7 +39,13 @@
@Override
public void sendToPlayer(ServerPlayer sender, boolean filterMaskEnabled, ChatType.Bound params) {
+ // Paper start
+ this.sendToPlayer(sender, filterMaskEnabled, params, null);
+ }
+ public void sendToPlayer(ServerPlayer sender, boolean filterMaskEnabled, ChatType.Bound params, @javax.annotation.Nullable Component unsigned) {
+ // Paper end
PlayerChatMessage playerChatMessage = this.message.filter(filterMaskEnabled);
+ playerChatMessage = unsigned != null ? playerChatMessage.withUnsignedContent(unsigned) : playerChatMessage; // Paper
if (!playerChatMessage.isFullyFiltered()) {
sender.connection.sendPlayerChatMessage(playerChatMessage, params);
}

View file

@ -1,37 +0,0 @@
--- a/net/minecraft/network/chat/TextColor.java
+++ b/net/minecraft/network/chat/TextColor.java
@@ -17,7 +17,7 @@
private static final String CUSTOM_COLOR_PREFIX = "#";
public static final Codec<TextColor> CODEC = Codec.STRING.comapFlatMap(TextColor::parseColor, TextColor::serialize);
private static final Map<ChatFormatting, TextColor> LEGACY_FORMAT_TO_COLOR = (Map) Stream.of(ChatFormatting.values()).filter(ChatFormatting::isColor).collect(ImmutableMap.toImmutableMap(Function.identity(), (enumchatformat) -> {
- return new TextColor(enumchatformat.getColor(), enumchatformat.getName());
+ return new TextColor(enumchatformat.getColor(), enumchatformat.getName(), enumchatformat); // CraftBukkit
}));
private static final Map<String, TextColor> NAMED_COLORS = (Map) TextColor.LEGACY_FORMAT_TO_COLOR.values().stream().collect(ImmutableMap.toImmutableMap((chathexcolor) -> {
return chathexcolor.name;
@@ -25,16 +25,22 @@
private final int value;
@Nullable
public final String name;
+ // CraftBukkit start
+ @Nullable
+ public final ChatFormatting format;
- private TextColor(int rgb, String name) {
- this.value = rgb & 16777215;
- this.name = name;
+ private TextColor(int i, String s, ChatFormatting format) {
+ this.value = i & 16777215;
+ this.name = s;
+ this.format = format;
}
private TextColor(int rgb) {
this.value = rgb & 16777215;
this.name = null;
+ this.format = null;
}
+ // CraftBukkit end
public int getValue() {
return this.value;