diff --git a/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/BukkitAudience.java b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/BukkitAudience.java index 733a8140..b6c8a98a 100644 --- a/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/BukkitAudience.java +++ b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/BukkitAudience.java @@ -49,6 +49,7 @@ final class BukkitAudience extends FacetAudience { () -> new ViaFacet.Chat<>(Player.class, VIA), // () -> new SpigotFacet.ChatWithType(), // () -> new SpigotFacet.Chat(), + () -> new CraftBukkitFacet.Chat1_19_3(), () -> new CraftBukkitFacet.Chat(), () -> new BukkitFacet.Chat()); private static final Collection> ACTION_BAR = Facet.of( diff --git a/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/BukkitFacet.java b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/BukkitFacet.java index fa5dc2cc..2628a264 100644 --- a/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/BukkitFacet.java +++ b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/BukkitFacet.java @@ -28,7 +28,6 @@ import java.util.Collection; import java.util.Set; import java.util.function.Function; -import net.kyori.adventure.audience.MessageType; import net.kyori.adventure.identity.Identity; import net.kyori.adventure.key.Key; import net.kyori.adventure.permission.PermissionChecker; @@ -79,7 +78,7 @@ protected Chat() { } @Override - public void sendMessage(final @NotNull CommandSender viewer, final @NotNull Identity source, final @NotNull String message, final @NotNull MessageType type) { + public void sendMessage(final @NotNull CommandSender viewer, final @NotNull Identity source, final @NotNull String message, final @NotNull Object type) { viewer.sendMessage(message); } } diff --git a/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/CraftBukkitAccess.java b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/CraftBukkitAccess.java new file mode 100644 index 00000000..1fdf7885 --- /dev/null +++ b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/CraftBukkitAccess.java @@ -0,0 +1,125 @@ +/* + * This file is part of adventure-platform, licensed under the MIT License. + * + * Copyright (c) 2018-2020 KyoriPowered + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package net.kyori.adventure.platform.bukkit; + +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Modifier; +import java.util.Optional; +import org.jetbrains.annotations.Nullable; + +import static net.kyori.adventure.platform.bukkit.MinecraftReflection.findClass; +import static net.kyori.adventure.platform.bukkit.MinecraftReflection.findConstructor; +import static net.kyori.adventure.platform.bukkit.MinecraftReflection.findMcClassName; +import static net.kyori.adventure.platform.bukkit.MinecraftReflection.findNmsClassName; +import static net.kyori.adventure.platform.bukkit.MinecraftReflection.searchMethod; +import static net.kyori.adventure.platform.facet.Knob.logError; + +final class CraftBukkitAccess { + static final @Nullable Class CLASS_CHAT_COMPONENT = findClass( + findNmsClassName("IChatBaseComponent"), + findMcClassName("network.chat.IChatBaseComponent"), + findMcClassName("network.chat.Component") + ); + static final @Nullable Class CLASS_REGISTRY = findClass( + findMcClassName("core.IRegistry"), + findMcClassName("core.Registry") + ); + static final @Nullable Class CLASS_SERVER_LEVEL = findClass( + findMcClassName("server.level.WorldServer"), + findMcClassName("server.level.ServerLevel") + ); + static final @Nullable Class CLASS_REGISTRY_ACCESS = findClass( + findMcClassName("core.IRegistryCustom"), + findMcClassName("core.RegistryAccess") + ); + static final @Nullable Class CLASS_RESOURCE_KEY = findClass(findMcClassName("resources.ResourceKey")); + static final @Nullable Class CLASS_RESOURCE_LOCATION = findClass( + findMcClassName("resources.MinecraftKey"), + findMcClassName("resources.ResourceLocation") + ); + + private CraftBukkitAccess() { + } + + static final class Chat1_19_3 { + static final @Nullable MethodHandle NEW_RESOURCE_LOCATION = findConstructor(CLASS_RESOURCE_LOCATION, String.class, String.class); + static final @Nullable MethodHandle RESOURCE_KEY_CREATE = searchMethod(CLASS_RESOURCE_KEY, Modifier.PUBLIC | Modifier.STATIC, "create", CLASS_RESOURCE_KEY, CLASS_RESOURCE_KEY, CLASS_RESOURCE_LOCATION); + static final @Nullable MethodHandle SERVER_PLAYER_GET_LEVEL = searchMethod(CraftBukkitFacet.CRAFT_PLAYER_GET_HANDLE.type().returnType(), Modifier.PUBLIC, "getLevel", CLASS_SERVER_LEVEL); + static final @Nullable MethodHandle SERVER_LEVEL_GET_REGISTRY_ACCESS = searchMethod(CLASS_SERVER_LEVEL, Modifier.PUBLIC, "registryAccess", CLASS_REGISTRY_ACCESS); + static final @Nullable MethodHandle REGISTRY_ACCESS_GET_REGISTRY_OPTIONAL = searchMethod(CLASS_REGISTRY_ACCESS, Modifier.PUBLIC, "registry", Optional.class, CLASS_RESOURCE_KEY); + static final @Nullable MethodHandle REGISTRY_GET_OPTIONAL = searchMethod(CLASS_REGISTRY, Modifier.PUBLIC, "getOptional", Optional.class, CLASS_RESOURCE_LOCATION); + static final @Nullable MethodHandle REGISTRY_GET_ID = searchMethod(CLASS_REGISTRY, Modifier.PUBLIC, "getId", int.class, Object.class); + static final @Nullable MethodHandle DISGUISED_CHAT_PACKET_CONSTRUCTOR; + static final @Nullable MethodHandle CHAT_TYPE_BOUND_NETWORK_CONSTRUCTOR; + + static final Object CHAT_TYPE_RESOURCE_KEY; + + static { + MethodHandle boundNetworkConstructor = null; + MethodHandle disguisedChatPacketConstructor = null; + Object chatTypeResourceKey = null; + + try { + Class classChatTypeBoundNetwork = findClass(findMcClassName("network.chat.ChatType$BoundNetwork")); + if (classChatTypeBoundNetwork == null) { + final Class parentClass = findClass(findMcClassName("network.chat.ChatMessageType")); + if (parentClass != null) { + for (final Class childClass : parentClass.getClasses()) { + boundNetworkConstructor = findConstructor(childClass, int.class, CLASS_CHAT_COMPONENT, CLASS_CHAT_COMPONENT); + if (boundNetworkConstructor != null) { + classChatTypeBoundNetwork = childClass; + break; + } + } + } + } + + final Class disguisedChatPacketClass = findClass(findMcClassName("network.protocol.game.ClientboundDisguisedChatPacket")); + if (disguisedChatPacketClass != null && classChatTypeBoundNetwork != null) { + disguisedChatPacketConstructor = findConstructor(disguisedChatPacketClass, CLASS_CHAT_COMPONENT, classChatTypeBoundNetwork); + } + + if (NEW_RESOURCE_LOCATION != null && RESOURCE_KEY_CREATE != null) { + final MethodHandle createRegistryKey = searchMethod(CLASS_RESOURCE_KEY, Modifier.PUBLIC | Modifier.STATIC, "createRegistryKey", CLASS_RESOURCE_KEY, CLASS_RESOURCE_LOCATION); + if (createRegistryKey != null) { + chatTypeResourceKey = createRegistryKey.invoke(NEW_RESOURCE_LOCATION.invoke("minecraft", "chat_type")); + } + } + } catch (final Throwable error) { + logError(error, "Failed to initialize 1.19.3 chat support"); + } + + DISGUISED_CHAT_PACKET_CONSTRUCTOR = disguisedChatPacketConstructor; + CHAT_TYPE_BOUND_NETWORK_CONSTRUCTOR = boundNetworkConstructor; + CHAT_TYPE_RESOURCE_KEY = chatTypeResourceKey; + } + + private Chat1_19_3() { + } + + static boolean isSupported() { + return SERVER_LEVEL_GET_REGISTRY_ACCESS != null && REGISTRY_ACCESS_GET_REGISTRY_OPTIONAL != null && REGISTRY_GET_OPTIONAL != null && CHAT_TYPE_BOUND_NETWORK_CONSTRUCTOR != null && DISGUISED_CHAT_PACKET_CONSTRUCTOR != null && CHAT_TYPE_RESOURCE_KEY != null; + } + } +} diff --git a/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/CraftBukkitFacet.java b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/CraftBukkitFacet.java index 53778cba..f9321bda 100644 --- a/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/CraftBukkitFacet.java +++ b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/CraftBukkitFacet.java @@ -45,6 +45,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -52,6 +53,7 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.function.Function; import net.kyori.adventure.audience.MessageType; +import net.kyori.adventure.chat.ChatType; import net.kyori.adventure.identity.Identity; import net.kyori.adventure.nbt.BinaryTagIO; import net.kyori.adventure.nbt.BinaryTagTypes; @@ -125,7 +127,7 @@ public boolean isSupported() { private static final Class CLASS_CRAFT_ENTITY = findCraftClass("entity.CraftEntity"); private static final MethodHandle CRAFT_ENTITY_GET_HANDLE = findMethod(CLASS_CRAFT_ENTITY, "getHandle", CLASS_NMS_ENTITY); static final @Nullable Class CLASS_CRAFT_PLAYER = findCraftClass("entity.CraftPlayer", Player.class); - private static final @Nullable MethodHandle CRAFT_PLAYER_GET_HANDLE; + static final @Nullable MethodHandle CRAFT_PLAYER_GET_HANDLE; private static final @Nullable MethodHandle ENTITY_PLAYER_GET_CONNECTION; private static final @Nullable MethodHandle PLAYER_CONNECTION_SEND_PACKET; @@ -239,7 +241,7 @@ public Object createMessage(final @NotNull V viewer, final @NotNull Component me } private static final @Nullable MethodHandle LEGACY_CHAT_PACKET_CONSTRUCTOR; // (IChatBaseComponent, byte) - private static final @Nullable MethodHandle CHAT_PACKET_CONSTRUCTOR; // (ChatMessageType, IChatBaseComponent, UUID) -> PacketPlayOutChat + private static final @Nullable MethodHandle CHAT_PACKET_CONSTRUCTOR; // (ChatMessageType, IChatBaseComponent, UUID) / (IChatBaseComponent, boolean) -> PacketPlayOutChat static { MethodHandle legacyChatPacketConstructor = null; @@ -295,6 +297,39 @@ public Object createMessage(final @NotNull V viewer, final @NotNull Component me LEGACY_CHAT_PACKET_CONSTRUCTOR = legacyChatPacketConstructor; } + static class Chat1_19_3 extends Chat { + @Override + public boolean isSupported() { + return super.isSupported() && CraftBukkitAccess.Chat1_19_3.isSupported(); + } + + @Override + public void sendMessage(final @NotNull CommandSender viewer, final @NotNull Identity source, final @NotNull Object message, final @NotNull Object type) { + if (!(type instanceof ChatType.Bound)) { + super.sendMessage(viewer, source, message, type); + } else { + final ChatType.Bound bound = (ChatType.Bound) type; + try { + final Object registryAccess = CraftBukkitAccess.Chat1_19_3.SERVER_LEVEL_GET_REGISTRY_ACCESS.invoke(CraftBukkitAccess.Chat1_19_3.SERVER_PLAYER_GET_LEVEL.invoke(CRAFT_PLAYER_GET_HANDLE.invoke(viewer))); + final Object chatTypeRegistry = ((Optional) CraftBukkitAccess.Chat1_19_3.REGISTRY_ACCESS_GET_REGISTRY_OPTIONAL.invoke(registryAccess, CraftBukkitAccess.Chat1_19_3.CHAT_TYPE_RESOURCE_KEY)).orElseThrow(NoSuchElementException::new); + final Object typeResourceLocation = CraftBukkitAccess.Chat1_19_3.NEW_RESOURCE_LOCATION.invoke(bound.type().key().namespace(), bound.type().key().value()); + final Object chatTypeObject = ((Optional) CraftBukkitAccess.Chat1_19_3.REGISTRY_GET_OPTIONAL.invoke(chatTypeRegistry, typeResourceLocation)).orElseThrow(NoSuchElementException::new); + final int networkId = (int) CraftBukkitAccess.Chat1_19_3.REGISTRY_GET_ID.invoke(chatTypeRegistry, chatTypeObject); + if (networkId < 0) { + throw new IllegalArgumentException("Could not get a valid network id from " + type); + } + final Object nameComponent = this.createMessage(viewer, bound.name()); + final Object targetComponent = bound.target() != null ? this.createMessage(viewer, bound.target()) : null; + final Object boundNetwork = CraftBukkitAccess.Chat1_19_3.CHAT_TYPE_BOUND_NETWORK_CONSTRUCTOR.invoke(networkId, nameComponent, targetComponent); + + this.sendMessage(viewer, CraftBukkitAccess.Chat1_19_3.DISGUISED_CHAT_PACKET_CONSTRUCTOR.invoke(message, boundNetwork)); + } catch (final Throwable error) { + logError(error, "Failed to send a 1.19.3+ message: %s %s", message, type); + } + } + } + } + static class Chat extends PacketFacet implements Facet.Chat { @Override public boolean isSupported() { @@ -302,7 +337,7 @@ public boolean isSupported() { } @Override - public void sendMessage(final @NotNull CommandSender viewer, final @NotNull Identity source, final @NotNull Object message, final @NotNull MessageType type) { + public void sendMessage(final @NotNull CommandSender viewer, final @NotNull Identity source, final @NotNull Object message, final @NotNull Object type) { final Object messageType = type == MessageType.CHAT ? MESSAGE_TYPE_CHAT : MESSAGE_TYPE_SYSTEM; try { this.sendMessage(viewer, CHAT_PACKET_CONSTRUCTOR.invoke(message, messageType, source.uuid())); diff --git a/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/MinecraftReflection.java b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/MinecraftReflection.java index c582d24a..021dc78d 100644 --- a/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/MinecraftReflection.java +++ b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/MinecraftReflection.java @@ -28,6 +28,7 @@ import java.lang.invoke.MethodType; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.Arrays; import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; @@ -175,7 +176,11 @@ public static MethodHandle searchMethod(final @Nullable Class holderClass, fi for (final String methodName : methodNames) { if (methodName == null) continue; try { - return LOOKUP.findVirtual(holderClass, methodName, MethodType.methodType(returnClass, parameterClasses)); + if (modifier != null && Modifier.isStatic(modifier)) { + return LOOKUP.findStatic(holderClass, methodName, MethodType.methodType(returnClass, parameterClasses)); + } else { + return LOOKUP.findVirtual(holderClass, methodName, MethodType.methodType(returnClass, parameterClasses)); + } } catch (final NoSuchMethodException | IllegalAccessException e) { } } @@ -184,7 +189,11 @@ public static MethodHandle searchMethod(final @Nullable Class holderClass, fi if ((modifier == null || (method.getModifiers() & modifier) == 0) || !Arrays.equals(method.getParameterTypes(), parameterClasses)) continue; try { - return LOOKUP.findVirtual(holderClass, method.getName(), MethodType.methodType(returnClass, parameterClasses)); + if (Modifier.isStatic(modifier)) { + return LOOKUP.findStatic(holderClass, method.getName(), MethodType.methodType(returnClass, parameterClasses)); + } else { + return LOOKUP.findVirtual(holderClass, method.getName(), MethodType.methodType(returnClass, parameterClasses)); + } } catch (final NoSuchMethodException | IllegalAccessException e) { } } diff --git a/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/SpigotFacet.java b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/SpigotFacet.java index dad076e6..aa80f482 100644 --- a/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/SpigotFacet.java +++ b/platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/SpigotFacet.java @@ -93,7 +93,7 @@ public boolean isSupported() { } @Override - public void sendMessage(final @NotNull CommandSender viewer, final @NotNull Identity source, final BaseComponent @NotNull[] message, final @NotNull MessageType type) { + public void sendMessage(final @NotNull CommandSender viewer, final @NotNull Identity source, final BaseComponent @NotNull[] message, final @NotNull Object type) { viewer.spigot().sendMessage(message); } } @@ -123,8 +123,8 @@ public boolean isSupported() { @Override @SuppressWarnings("deprecation") - public void sendMessage(final @NotNull Player viewer, final @NotNull Identity source, final BaseComponent @NotNull[] message, final @NotNull MessageType type) { - final ChatMessageType chat = this.createType(type); + public void sendMessage(final @NotNull Player viewer, final @NotNull Identity source, final BaseComponent @NotNull[] message, final @NotNull Object type) { + final ChatMessageType chat = type instanceof MessageType ? this.createType((MessageType) type) : ChatMessageType.SYSTEM; // if it's not a legacy adventure MessageType it doesn't matter cause its not used if (chat != null) { viewer.spigot().sendMessage(chat, message); } diff --git a/platform-bungeecord/src/main/java/net/kyori/adventure/platform/bungeecord/BungeeFacet.java b/platform-bungeecord/src/main/java/net/kyori/adventure/platform/bungeecord/BungeeFacet.java index 5324a858..96ad3220 100644 --- a/platform-bungeecord/src/main/java/net/kyori/adventure/platform/bungeecord/BungeeFacet.java +++ b/platform-bungeecord/src/main/java/net/kyori/adventure/platform/bungeecord/BungeeFacet.java @@ -93,7 +93,7 @@ public boolean isApplicable(final @NotNull CommandSender viewer) { } @Override - public void sendMessage(final @NotNull CommandSender viewer, final @NotNull Identity source, final BaseComponent @NotNull [] message, final @NotNull MessageType type) { + public void sendMessage(final @NotNull CommandSender viewer, final @NotNull Identity source, final BaseComponent @NotNull [] message, final @NotNull Object type) { viewer.sendMessage(message); } } @@ -134,7 +134,7 @@ public boolean isSupported() { } @Override - public void sendMessage(final @NotNull ProxiedPlayer viewer, final @NotNull Identity source, final BaseComponent @NotNull [] message, final @NotNull MessageType type) { + public void sendMessage(final @NotNull ProxiedPlayer viewer, final @NotNull Identity source, final BaseComponent @NotNull [] message, final @NotNull Object type) { if (type == MessageType.CHAT) { viewer.sendMessage(source.uuid(), message); } else { @@ -155,8 +155,8 @@ static class ChatPlayer extends Message implements Facet.Chat extends Message { * @param type a message type * @since 4.0.0 */ - void sendMessage(final @NotNull V viewer, final @NotNull Identity source, final @NotNull M message, final @NotNull MessageType type); + void sendMessage(final @NotNull V viewer, final @NotNull Identity source, final @NotNull M message, final @NotNull Object type); } /** diff --git a/platform-facet/src/main/java/net/kyori/adventure/platform/facet/FacetAudience.java b/platform-facet/src/main/java/net/kyori/adventure/platform/facet/FacetAudience.java index 5f7565d6..efc16d79 100644 --- a/platform-facet/src/main/java/net/kyori/adventure/platform/facet/FacetAudience.java +++ b/platform-facet/src/main/java/net/kyori/adventure/platform/facet/FacetAudience.java @@ -36,6 +36,8 @@ import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.MessageType; import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.chat.ChatType; +import net.kyori.adventure.chat.SignedMessage; import net.kyori.adventure.identity.Identity; import net.kyori.adventure.pointer.Pointers; import net.kyori.adventure.sound.Sound; @@ -194,6 +196,34 @@ public void sendMessage(final @NotNull Identity source, final @NotNull Component } } + @Override + public void sendMessage(final @NotNull Component original, final ChatType.@NotNull Bound boundChatType) { + if (this.chat == null) return; + final Object message = this.createMessage(original, this.chat); + if (message == null) return; + + final Component name = this.provider.componentRenderer.render(boundChatType.name(), this); + Component target = null; + if (boundChatType.target() != null) { + target = this.provider.componentRenderer.render(boundChatType.target(), this); + } + final Object renderedType = boundChatType.type().bind(name, target); + + for (final V viewer : this.viewers) { + this.chat.sendMessage(viewer, Identity.nil(), message, renderedType); + } + } + + @Override + public void sendMessage(final @NotNull SignedMessage signedMessage, final ChatType.@NotNull Bound boundChatType) { + if (signedMessage.isSystem()) { + final Component content = signedMessage.unsignedContent() != null ? signedMessage.unsignedContent() : Component.text(signedMessage.message()); + this.sendMessage(content, boundChatType); + } else { + Audience.super.sendMessage(signedMessage, boundChatType); + } + } + @Override public void sendActionBar(final @NotNull Component original) { if (this.actionBar == null) return; diff --git a/platform-spongeapi/src/main/java/net/kyori/adventure/platform/spongeapi/SpongeFacet.java b/platform-spongeapi/src/main/java/net/kyori/adventure/platform/spongeapi/SpongeFacet.java index 99103026..d0a0e4a3 100644 --- a/platform-spongeapi/src/main/java/net/kyori/adventure/platform/spongeapi/SpongeFacet.java +++ b/platform-spongeapi/src/main/java/net/kyori/adventure/platform/spongeapi/SpongeFacet.java @@ -112,7 +112,7 @@ protected Chat() { } @Override - public void sendMessage(final @NotNull MessageReceiver viewer, final @NotNull Identity source, final @NotNull Text message, final @NotNull MessageType type) { + public void sendMessage(final @NotNull MessageReceiver viewer, final @NotNull Identity source, final @NotNull Text message, final @NotNull Object type) { viewer.sendMessage(message); } } @@ -133,8 +133,8 @@ protected ChatWithType() { } @Override - public void sendMessage(final @NotNull ChatTypeMessageReceiver viewer, final @NotNull Identity source, final @NotNull Text message, final @NotNull MessageType type) { - final ChatType chat = this.type(type); + public void sendMessage(final @NotNull ChatTypeMessageReceiver viewer, final @NotNull Identity source, final @NotNull Text message, final @NotNull Object type) { + final ChatType chat = type instanceof MessageType ? this.type((MessageType) type) : ChatTypes.SYSTEM; if (chat != null) { viewer.sendMessage(chat, message); } diff --git a/platform-viaversion/src/main/java/net/kyori/adventure/platform/viaversion/ViaFacet.java b/platform-viaversion/src/main/java/net/kyori/adventure/platform/viaversion/ViaFacet.java index 219b7fcf..357baac5 100644 --- a/platform-viaversion/src/main/java/net/kyori/adventure/platform/viaversion/ViaFacet.java +++ b/platform-viaversion/src/main/java/net/kyori/adventure/platform/viaversion/ViaFacet.java @@ -184,10 +184,10 @@ public Chat(final @NotNull Class viewerClass, final @NotNull Functi } @Override - public void sendMessage(final @NotNull V viewer, final @NotNull Identity source, final @NotNull String message, final @NotNull MessageType type) { + public void sendMessage(final @NotNull V viewer, final @NotNull Identity source, final @NotNull String message, final @NotNull Object type) { final PacketWrapper packet = this.createPacket(viewer); packet.write(Type.COMPONENT, this.parse(message)); - packet.write(Type.BYTE, this.createMessageType(type)); + packet.write(Type.BYTE, this.createMessageType(type instanceof MessageType ? (MessageType) type : MessageType.SYSTEM)); packet.write(Type.UUID, source.uuid()); this.sendPacket(packet); }