Archiviert
13
0

Rework the component array modifier to work in 1.9.4 and up

Fixes #215
Dieser Commit ist enthalten in:
Dan Mulloy 2016-07-03 13:12:24 -04:00
Ursprung a995866d5b
Commit e34105e754
2 geänderte Dateien mit 118 neuen und 11 gelöschten Zeilen

Datei anzeigen

@ -17,9 +17,6 @@
package com.comphenix.protocol.events; package com.comphenix.protocol.events;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import java.io.DataInput; import java.io.DataInput;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutput; import java.io.DataOutput;
@ -105,11 +102,16 @@ import com.comphenix.protocol.wrappers.WrappedServerPing;
import com.comphenix.protocol.wrappers.WrappedStatistic; import com.comphenix.protocol.wrappers.WrappedStatistic;
import com.comphenix.protocol.wrappers.WrappedWatchableObject; import com.comphenix.protocol.wrappers.WrappedWatchableObject;
import com.comphenix.protocol.wrappers.nbt.NbtBase; import com.comphenix.protocol.wrappers.nbt.NbtBase;
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
/** /**
* Represents a Minecraft packet indirectly. * Represents a Minecraft packet indirectly.
* *
@ -659,15 +661,19 @@ public class PacketContainer implements Serializable {
/** /**
* Retrieves a read/write structure for arrays of chat components. * Retrieves a read/write structure for arrays of chat components.
* <p> * <p>
* This modifier will automatically marshall between WrappedChatComponent and the * This modifier will automatically marshal between WrappedChatComponent and the
* internal Minecraft IChatBaseComponent. * internal Minecraft IChatBaseComponent (1.9.2 and below) or the internal
* NBTCompound (1.9.4 and up).
* <p>
* Note that in 1.9.4 and up this modifier only works properly with sign
* tile entities.
* @return A modifier for ChatComponent array fields. * @return A modifier for ChatComponent array fields.
*/ */
public StructureModifier<WrappedChatComponent[]> getChatComponentArrays() { public StructureModifier<WrappedChatComponent[]> getChatComponentArrays() {
// Convert to and from the Bukkit wrapper // Convert to and from the Bukkit wrapper
return structureModifier.<WrappedChatComponent[]>withType( return structureModifier.<WrappedChatComponent[]>withType(
MinecraftReflection.getIChatBaseComponentArrayClass(), ComponentArrayConverter.getGenericType(),
BukkitConverters.getIgnoreNull(new WrappedChatComponentArrayConverter())); BukkitConverters.getIgnoreNull(new ComponentArrayConverter()));
} }
/** /**
@ -1076,7 +1082,7 @@ public class PacketContainer implements Serializable {
* Construct a new packet data serializer. * Construct a new packet data serializer.
* @return The packet data serializer. * @return The packet data serializer.
*/ */
private ByteBuf createPacketBuffer() { public static ByteBuf createPacketBuffer() {
ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer(); ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
Class<?> packetSerializer = MinecraftReflection.getPacketDataSerializerClass(); Class<?> packetSerializer = MinecraftReflection.getPacketDataSerializerClass();
@ -1224,7 +1230,7 @@ public class PacketContainer implements Serializable {
* Represents an equivalent converter for ChatComponent arrays. * Represents an equivalent converter for ChatComponent arrays.
* @author dmulloy2 * @author dmulloy2
*/ */
private static class WrappedChatComponentArrayConverter implements EquivalentConverter<WrappedChatComponent[]> { private static class LegacyComponentConverter implements EquivalentConverter<WrappedChatComponent[]> {
final EquivalentConverter<WrappedChatComponent> componentConverter = BukkitConverters.getWrappedChatComponentConverter(); final EquivalentConverter<WrappedChatComponent> componentConverter = BukkitConverters.getWrappedChatComponentConverter();
@Override @Override
@ -1257,6 +1263,94 @@ public class PacketContainer implements Serializable {
} }
} }
/**
* Converts from NBT to WrappedChatComponent arrays
* @author dmulloy2
*/
private static class NBTComponentConverter implements EquivalentConverter<WrappedChatComponent[]> {
private EquivalentConverter<NbtBase<?>> nbtConverter = BukkitConverters.getNbtConverter();
private final int lines = 4;
@Override
public WrappedChatComponent[] getSpecific(Object generic) {
NbtBase<?> nbtBase = nbtConverter.getSpecific(generic);
NbtCompound compound = (NbtCompound) nbtBase;
WrappedChatComponent[] components = new WrappedChatComponent[lines];
for (int i = 0; i < lines; i++) {
if (compound.containsKey("Text" + (i + 1))) {
components[i] = WrappedChatComponent.fromJson(compound.getString("Text" + (i + 1)));
} else {
components[i] = WrappedChatComponent.fromText("");
}
}
return components;
}
@Override
public Object getGeneric(Class<?> genericType, WrappedChatComponent[] specific) {
NbtCompound compound = NbtFactory.ofCompound("");
for (int i = 0; i < lines; i++) {
WrappedChatComponent component;
if (i < specific.length && specific[i] != null) {
component = specific[i];
} else {
component = WrappedChatComponent.fromText("");
}
compound.put("Text" + (i + 1), component.getJson());
}
return nbtConverter.getGeneric(genericType, compound);
}
@Override
public Class<WrappedChatComponent[]> getSpecificType() {
return WrappedChatComponent[].class;
}
}
/**
* A delegated converter that supports NBT to Component Array and regular Component Array
* @author dmulloy2
*/
private static class ComponentArrayConverter implements EquivalentConverter<WrappedChatComponent[]> {
private static final EquivalentConverter<WrappedChatComponent[]> DELEGATE;
static {
Class<?> packetClass = PacketType.Play.Server.UPDATE_SIGN.getPacketClass();
if (packetClass.getName().contains("Sign")) {
DELEGATE = new LegacyComponentConverter();
} else {
DELEGATE = new NBTComponentConverter();
}
}
@Override
public WrappedChatComponent[] getSpecific(Object generic) {
return DELEGATE.getSpecific(generic);
}
@Override
public Object getGeneric(Class<?> genericType, WrappedChatComponent[] specific) {
return DELEGATE.getGeneric(genericType, specific);
}
@Override
public Class<WrappedChatComponent[]> getSpecificType() {
return DELEGATE.getSpecificType();
}
public static Class<?> getGenericType() {
if (DELEGATE instanceof NBTComponentConverter) {
return MinecraftReflection.getNBTCompoundClass();
} else {
return MinecraftReflection.getIChatBaseComponentArrayClass();
}
}
}
@Override @Override
public String toString() { public String toString() {
return "PacketContainer[type=" + type + ", structureModifier=" + structureModifier + "]"; return "PacketContainer[type=" + type + ", structureModifier=" + structureModifier + "]";

Datei anzeigen

@ -520,6 +520,19 @@ public class PacketContainerTest {
UPDATE_PROPERTIES; UPDATE_PROPERTIES;
} }
@Test
public void testComponentArrays() {
PacketContainer signChange = new PacketContainer(PacketType.Play.Server.TILE_ENTITY_DATA);
WrappedChatComponent[] components = new WrappedChatComponent[] {
WrappedChatComponent.fromText("hello world"), WrappedChatComponent.fromText(""),
WrappedChatComponent.fromText(""), WrappedChatComponent.fromText("")
};
signChange.getChatComponentArrays().write(0, components);
WrappedChatComponent[] back = signChange.getChatComponentArrays().read(0);
assertArrayEquals(components, back);
}
private static final List<PacketType> BLACKLISTED = Util.asList( private static final List<PacketType> BLACKLISTED = Util.asList(
PacketType.Play.Client.CUSTOM_PAYLOAD, PacketType.Play.Server.CUSTOM_PAYLOAD, PacketType.Play.Client.CUSTOM_PAYLOAD, PacketType.Play.Server.CUSTOM_PAYLOAD,
PacketType.Play.Server.SET_COOLDOWN PacketType.Play.Server.SET_COOLDOWN