Skip to content

Commit

Permalink
Add support for replacing chat info messages in 1.19+
Browse files Browse the repository at this point in the history
  • Loading branch information
kangarko committed Apr 14, 2023
1 parent 19206f5 commit 8374209
Showing 1 changed file with 73 additions and 6 deletions.
79 changes: 73 additions & 6 deletions src/main/java/org/mineacademy/fo/model/PacketListener.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.mineacademy.fo.model;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
Expand All @@ -11,6 +13,7 @@
import org.mineacademy.fo.Common;
import org.mineacademy.fo.MinecraftVersion;
import org.mineacademy.fo.MinecraftVersion.V;
import org.mineacademy.fo.ReflectionUtil;
import org.mineacademy.fo.collection.SerializedMap;
import org.mineacademy.fo.exception.EventHandledException;
import org.mineacademy.fo.exception.FoException;
Expand All @@ -26,18 +29,26 @@
import com.comphenix.protocol.wrappers.EnumWrappers.ChatType;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedServerPing;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;

/**
* Represents packet handling using ProtocolLib
*/
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public abstract class PacketListener {

/**
* Stores 1.19 system chat packet constructor and Adventure stuff for maximum performance
*/
private static Constructor<?> packetConst;
private static Class<?> textComponentClass;

/**
* Called automatically when you use \@AutoRegister, inject
* your packet listeners here.
Expand Down Expand Up @@ -156,6 +167,24 @@ protected List<WrappedGameProfile> compileHoverText(final String... hoverTexts)
return profiles;
}

// ------------------------------------------------------------------------------------------------------------
// Stati
// ------------------------------------------------------------------------------------------------------------

/*
* Sends a system chat packet to the player
*/
private static void sendSystemChatPacket(Player player, String message) {
if (packetConst == null) {
Class<?> packetClass = ReflectionUtil.lookupClass("net.minecraft.network.protocol.game.ClientboundSystemChatPacket");

packetConst = ReflectionUtil.getConstructor(packetClass, BaseComponent[].class, boolean.class);
}

Object newPacket = ReflectionUtil.instantiate(packetConst, TextComponent.fromLegacyText(message), false /* not on action bar */);
Remain.sendPacket(player, newPacket);
}

// ------------------------------------------------------------------------------------------------------------
// Classes
// ------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -280,12 +309,25 @@ private String compileChatMessage(PacketEvent event) {
// Reset
this.jsonMessage = null;

// No components for this MC version
// Components
if (MinecraftVersion.atLeast(V.v1_7)) {
if (this.systemChat)

// System chat
if (this.systemChat) {
this.jsonMessage = event.getPacket().getStrings().read(0);

else {
final Object adventureContent = ReflectionUtil.getFieldContent(event.getPacket().getHandle(), "adventure$content");

if (adventureContent != null) {
final List<String> contents = new ArrayList<>();

this.mergeChildren(adventureContent, contents);
final String mergedContents = String.join("", contents);

return mergedContents;
}

} else {

final StructureModifier<Object> packet = event.getPacket().getModifier();
final StructureModifier<WrappedChatComponent> chat = event.getPacket().getChatComponents();
Expand Down Expand Up @@ -325,6 +367,7 @@ else if (packet.size() > 1) {
}
}

// No components for this MC version
else
this.jsonMessage = event.getPacket().getStrings().read(0);

Expand All @@ -349,6 +392,24 @@ else if (packet.size() > 1) {
return "";
}

/*
* Helper method to get content of all children of the given component
*/
private void mergeChildren(Object component, List<String> contents) {
final Method contentMethod = ReflectionUtil.getMethod(component.getClass(), "content");
final Method childrenMethod = ReflectionUtil.getMethod(component.getClass(), "children");

if (textComponentClass == null)
textComponentClass = ReflectionUtil.lookupClass("net.kyori.adventure.text.TextComponent");

if (textComponentClass.isAssignableFrom(component.getClass())) {
contents.add(ReflectionUtil.invoke(contentMethod, component));

for (Object child : (List<?>) ReflectionUtil.invoke(childrenMethod, component))
mergeChildren(child, contents);
}
}

/*
* Writes the edited message as JSON format from the event
*/
Expand All @@ -357,9 +418,15 @@ private void writeEditedMessage(String message, PacketEvent event) {

this.jsonMessage = Remain.toJson(message);

if (this.systemChat)
event.getPacket().getStrings().writeSafely(0, this.jsonMessage);
else if (this.isBaseComponent)
if (this.systemChat) {

// Need to cancel due to Record class having final fields and write our own packet, so much for simplicity of Adventure-Paper impl
event.setCancelled(true);

// We simply send a new packet instead
sendSystemChatPacket(this.player, message);

} else if (this.isBaseComponent)
packet.writeSafely(this.adventure ? 2 : 1, Remain.toComponent(this.jsonMessage));

else if (MinecraftVersion.atLeast(V.v1_7))
Expand Down

0 comments on commit 8374209

Please sign in to comment.