diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/events/PacketContainer.java b/ProtocolLib/src/main/java/com/comphenix/protocol/events/PacketContainer.java index 87f0139c..9fcdea35 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/events/PacketContainer.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/events/PacketContainer.java @@ -66,6 +66,7 @@ import com.comphenix.protocol.utility.StreamSerializer; import com.comphenix.protocol.wrappers.BukkitConverters; import com.comphenix.protocol.wrappers.ChunkPosition; import com.comphenix.protocol.wrappers.WrappedAttribute; +import com.comphenix.protocol.wrappers.WrappedChatComponent; import com.comphenix.protocol.wrappers.WrappedDataWatcher; import com.comphenix.protocol.wrappers.WrappedGameProfile; import com.comphenix.protocol.wrappers.WrappedWatchableObject; @@ -478,7 +479,7 @@ public class PacketContainer implements Serializable { } /** - * Retrieves a read/write structure for game profiles. + * Retrieves a read/write structure for game profiles in Minecraft 1.7.2. *
* This modifier will automatically marshall between WrappedGameProfile and the * internal Minecraft GameProfile. @@ -490,6 +491,19 @@ public class PacketContainer implements Serializable { GameProfile.class, BukkitConverters.getWrappedGameProfileConverter()); } + /** + * Retrieves a read/write structure for chat components in Minecraft 1.7.2. + *
+ * This modifier will automatically marshall between WrappedChatComponent and the
+ * internal Minecraft GameProfile.
+ * @return A modifier for GameProfile fields.
+ */
+ public StructureModifier
diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/ClassAnalyser.java b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/ClassAnalyser.java
index 03c62442..5a4b4eff 100644
--- a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/ClassAnalyser.java
+++ b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/ClassAnalyser.java
@@ -6,6 +6,7 @@ import java.util.List;
import com.comphenix.protocol.reflect.compiler.EmptyClassVisitor;
import com.comphenix.protocol.reflect.compiler.EmptyMethodVisitor;
+import com.comphenix.protocol.utility.MinecraftReflection;
import com.google.common.collect.Lists;
import net.sf.cglib.asm.ClassReader;
@@ -28,10 +29,19 @@ public class ClassAnalyser {
this.signature = signature;
}
- public String getOwnerClass() {
+ public String getOwnerName() {
return ownerClass;
}
+ /**
+ * Retrieve the associated owner class.
+ * @return The owner class.
+ * @throws ClassNotFoundException
+ */
+ public Class> getOwnerClass() throws ClassNotFoundException {
+ return AsmMethod.class.getClassLoader().loadClass(getOwnerName().replace('/', '.'));
+ }
+
public String getMethodName() {
return methodName;
}
@@ -57,7 +67,18 @@ public class ClassAnalyser {
* @throws IOException Cannot access the parent class.
*/
public List
@@ -1300,7 +1354,7 @@ public class MinecraftReflection {
try {
// Now -- we inspect all the method calls within that method, and use the first foreign Minecraft class
for (AsmMethod method : ClassAnalyser.getDefault().getMethodCalls(writeNbt)) {
- Class> owner = MinecraftReflection.class.getClassLoader().loadClass(method.getOwnerClass().replace('/', '.'));
+ Class> owner = method.getOwnerClass();
if (!packetSerializer.equals(owner) && isMinecraftClass(owner)) {
return setMinecraftClass("NBTCompressedStreamTools", owner);
diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java b/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java
index 301f9a0f..d26fd7c5 100644
--- a/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java
+++ b/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java
@@ -257,6 +257,29 @@ public class BukkitConverters {
};
}
+ /**
+ * Retrieve a converter for wrapped chat components.
+ * @return Wrapped chat componetns.
+ */
+ public static EquivalentConverter
+ * This uses {@link ChatColor} for formating.
+ * @param message - the message.
+ * @return The equivalent chat components.
+ */
+ public static WrappedChatComponent[] fromChatMessage(String message) {
+ Object[] components = (Object[]) CONSTRUCT_COMPONENT.invoke(null, message);
+ WrappedChatComponent[] result = new WrappedChatComponent[components.length];
+
+ for (int i = 0; i < components.length; i++) {
+ result[i] = fromHandle(components[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Retrieve a copy of this component as a JSON string.
+ *
+ * Note that any modifications to this JSON string will not update the current component.
+ * @return The JSON representation of this object.
+ */
+ public String getJson() {
+ if (cache == null) {
+ cache = (String) SERIALIZE_COMPONENT.invoke(null, handle);
+ }
+ return cache;
+ }
+
+ /**
+ * Set the content of this component using a JSON object.
+ * @param obj - the JSON that represents the new component.
+ */
+ public void setJson(String obj) {
+ this.handle = DESERIALIZE_COMPONENT.invoke(null, obj);
+ this.cache = obj;
+ }
+
+ /**
+ * Retrieve the underlying IChatBaseComponent instance.
+ * @return The underlying instance.
+ */
+ public Object getHandle() {
+ return handle;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+ if (obj instanceof WrappedChatComponent) {
+ return ((WrappedChatComponent) obj).handle.equals(handle);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return handle.hashCode();
+ }
+}
diff --git a/ProtocolLib/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java b/ProtocolLib/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java
index 51fa812a..2f67d4c7 100644
--- a/ProtocolLib/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java
+++ b/ProtocolLib/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java
@@ -32,6 +32,7 @@ import org.apache.commons.lang.builder.ToStringStyle;
// Will have to be updated for every version though
import org.bukkit.craftbukkit.v1_7_R1.inventory.CraftItemFactory;
+import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.WorldType;
import org.bukkit.inventory.ItemStack;
@@ -53,6 +54,7 @@ import com.comphenix.protocol.utility.MinecraftMethods;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.BukkitConverters;
import com.comphenix.protocol.wrappers.ChunkPosition;
+import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
@@ -336,6 +338,16 @@ public class PacketContainerTest {
assertEquals(profile, spawnEntity.getGameProfiles().read(0));
}
+ @Test
+ public void testChatComponents() {
+ PacketContainer chatPacket = new PacketContainer(PacketType.Play.Server.CHAT);
+ chatPacket.getChatComponents().write(0,
+ WrappedChatComponent.fromChatMessage("You shall not " + ChatColor.ITALIC + "pass!")[0]);
+
+ assertEquals("{\"extra\":[\"You shall not \",{\"italic\":true,\"text\":\"pass!\"}],\"text\":\"\"}",
+ chatPacket.getChatComponents().read(0).getJson());
+ }
+
@Test
public void testSerialization() {
PacketContainer chat = new PacketContainer(PacketType.Play.Client.CHAT);
diff --git a/ProtocolLib/src/test/java/com/comphenix/protocol/utility/MinecraftReflectionTest.java b/ProtocolLib/src/test/java/com/comphenix/protocol/utility/MinecraftReflectionTest.java
index b2473478..5192e6bb 100644
--- a/ProtocolLib/src/test/java/com/comphenix/protocol/utility/MinecraftReflectionTest.java
+++ b/ProtocolLib/src/test/java/com/comphenix/protocol/utility/MinecraftReflectionTest.java
@@ -2,6 +2,8 @@ package com.comphenix.protocol.utility;
import static org.junit.Assert.*;
+import net.minecraft.server.v1_7_R1.ChatSerializer;
+import net.minecraft.server.v1_7_R1.IChatBaseComponent;
import net.minecraft.server.v1_7_R1.NBTCompressedStreamTools;
import org.junit.AfterClass;
@@ -32,4 +34,14 @@ public class MinecraftReflectionTest {
public void testNbtStreamTools() {
assertEquals(NBTCompressedStreamTools.class, MinecraftReflection.getNbtCompressedStreamToolsClass());
}
+
+ @Test
+ public void testChatComponent() {
+ assertEquals(IChatBaseComponent.class, MinecraftReflection.getIChatBaseComponent());
+ }
+
+ @Test
+ public void testChatSerializer() {
+ assertEquals(ChatSerializer.class, MinecraftReflection.getChatSerializer());
+ }
}