|
17 | 17 |
|
18 | 18 | package com.comphenix.protocol.events;
|
19 | 19 |
|
20 |
| -import io.netty.buffer.ByteBuf; |
21 |
| -import io.netty.buffer.UnpooledByteBufAllocator; |
22 |
| - |
23 | 20 | import java.io.DataInput;
|
24 | 21 | import java.io.DataInputStream;
|
25 | 22 | import java.io.DataOutput;
|
|
105 | 102 | import com.comphenix.protocol.wrappers.WrappedStatistic;
|
106 | 103 | import com.comphenix.protocol.wrappers.WrappedWatchableObject;
|
107 | 104 | import com.comphenix.protocol.wrappers.nbt.NbtBase;
|
| 105 | +import com.comphenix.protocol.wrappers.nbt.NbtCompound; |
| 106 | +import com.comphenix.protocol.wrappers.nbt.NbtFactory; |
108 | 107 | import com.google.common.base.Function;
|
109 | 108 | import com.google.common.base.Preconditions;
|
110 | 109 | import com.google.common.collect.Maps;
|
111 | 110 | import com.google.common.collect.Sets;
|
112 | 111 |
|
| 112 | +import io.netty.buffer.ByteBuf; |
| 113 | +import io.netty.buffer.UnpooledByteBufAllocator; |
| 114 | + |
113 | 115 | /**
|
114 | 116 | * Represents a Minecraft packet indirectly.
|
115 | 117 | *
|
@@ -659,15 +661,19 @@ public StructureModifier<WrappedChatComponent> getChatComponents() {
|
659 | 661 | /**
|
660 | 662 | * Retrieves a read/write structure for arrays of chat components.
|
661 | 663 | * <p>
|
662 |
| - * This modifier will automatically marshall between WrappedChatComponent and the |
663 |
| - * internal Minecraft IChatBaseComponent. |
| 664 | + * This modifier will automatically marshal between WrappedChatComponent and the |
| 665 | + * internal Minecraft IChatBaseComponent (1.9.2 and below) or the internal |
| 666 | + * NBTCompound (1.9.4 and up). |
| 667 | + * <p> |
| 668 | + * Note that in 1.9.4 and up this modifier only works properly with sign |
| 669 | + * tile entities. |
664 | 670 | * @return A modifier for ChatComponent array fields.
|
665 | 671 | */
|
666 | 672 | public StructureModifier<WrappedChatComponent[]> getChatComponentArrays() {
|
667 | 673 | // Convert to and from the Bukkit wrapper
|
668 | 674 | return structureModifier.<WrappedChatComponent[]>withType(
|
669 |
| - MinecraftReflection.getIChatBaseComponentArrayClass(), |
670 |
| - BukkitConverters.getIgnoreNull(new WrappedChatComponentArrayConverter())); |
| 675 | + ComponentArrayConverter.getGenericType(), |
| 676 | + BukkitConverters.getIgnoreNull(new ComponentArrayConverter())); |
671 | 677 | }
|
672 | 678 |
|
673 | 679 | /**
|
@@ -923,7 +929,7 @@ public <T extends Enum<T>> StructureModifier<T> getEnumModifier(Class<T> enumCla
|
923 | 929 | */
|
924 | 930 | public <T extends Enum<T>> StructureModifier<T> getEnumModifier(Class<T> enumClass, int index) {
|
925 | 931 | return getEnumModifier(enumClass, structureModifier.getField(index).getType());
|
926 |
| - } |
| 932 | + } |
927 | 933 |
|
928 | 934 | /**
|
929 | 935 | * Retrieves the ID of this packet.
|
@@ -1076,7 +1082,7 @@ private void readObject(ObjectInputStream input) throws ClassNotFoundException,
|
1076 | 1082 | * Construct a new packet data serializer.
|
1077 | 1083 | * @return The packet data serializer.
|
1078 | 1084 | */
|
1079 |
| - private ByteBuf createPacketBuffer() { |
| 1085 | + public static ByteBuf createPacketBuffer() { |
1080 | 1086 | ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
|
1081 | 1087 | Class<?> packetSerializer = MinecraftReflection.getPacketDataSerializerClass();
|
1082 | 1088 |
|
@@ -1224,11 +1230,11 @@ public Class<ItemStack[]> getSpecificType() {
|
1224 | 1230 | * Represents an equivalent converter for ChatComponent arrays.
|
1225 | 1231 | * @author dmulloy2
|
1226 | 1232 | */
|
1227 |
| - private static class WrappedChatComponentArrayConverter implements EquivalentConverter<WrappedChatComponent[]> { |
| 1233 | + private static class LegacyComponentConverter implements EquivalentConverter<WrappedChatComponent[]> { |
1228 | 1234 | final EquivalentConverter<WrappedChatComponent> componentConverter = BukkitConverters.getWrappedChatComponentConverter();
|
1229 | 1235 |
|
1230 | 1236 | @Override
|
1231 |
| - public Object getGeneric(Class<?>genericType, WrappedChatComponent[] specific) { |
| 1237 | + public Object getGeneric(Class<?> genericType, WrappedChatComponent[] specific) { |
1232 | 1238 | Class<?> nmsComponent = MinecraftReflection.getIChatBaseComponentClass();
|
1233 | 1239 | Object[] result = (Object[]) Array.newInstance(nmsComponent, specific.length);
|
1234 | 1240 |
|
@@ -1257,6 +1263,94 @@ public Class<WrappedChatComponent[]> getSpecificType() {
|
1257 | 1263 | }
|
1258 | 1264 | }
|
1259 | 1265 |
|
| 1266 | + /** |
| 1267 | + * Converts from NBT to WrappedChatComponent arrays |
| 1268 | + * @author dmulloy2 |
| 1269 | + */ |
| 1270 | + private static class NBTComponentConverter implements EquivalentConverter<WrappedChatComponent[]> { |
| 1271 | + private EquivalentConverter<NbtBase<?>> nbtConverter = BukkitConverters.getNbtConverter(); |
| 1272 | + private final int lines = 4; |
| 1273 | + |
| 1274 | + @Override |
| 1275 | + public WrappedChatComponent[] getSpecific(Object generic) { |
| 1276 | + NbtBase<?> nbtBase = nbtConverter.getSpecific(generic); |
| 1277 | + NbtCompound compound = (NbtCompound) nbtBase; |
| 1278 | + |
| 1279 | + WrappedChatComponent[] components = new WrappedChatComponent[lines]; |
| 1280 | + for (int i = 0; i < lines; i++) { |
| 1281 | + if (compound.containsKey("Text" + (i + 1))) { |
| 1282 | + components[i] = WrappedChatComponent.fromJson(compound.getString("Text" + (i + 1))); |
| 1283 | + } else { |
| 1284 | + components[i] = WrappedChatComponent.fromText(""); |
| 1285 | + } |
| 1286 | + } |
| 1287 | + |
| 1288 | + return components; |
| 1289 | + } |
| 1290 | + |
| 1291 | + @Override |
| 1292 | + public Object getGeneric(Class<?> genericType, WrappedChatComponent[] specific) { |
| 1293 | + NbtCompound compound = NbtFactory.ofCompound(""); |
| 1294 | + |
| 1295 | + for (int i = 0; i < lines; i++) { |
| 1296 | + WrappedChatComponent component; |
| 1297 | + if (i < specific.length && specific[i] != null) { |
| 1298 | + component = specific[i]; |
| 1299 | + } else { |
| 1300 | + component = WrappedChatComponent.fromText(""); |
| 1301 | + } |
| 1302 | + |
| 1303 | + compound.put("Text" + (i + 1), component.getJson()); |
| 1304 | + } |
| 1305 | + |
| 1306 | + return nbtConverter.getGeneric(genericType, compound); |
| 1307 | + } |
| 1308 | + |
| 1309 | + @Override |
| 1310 | + public Class<WrappedChatComponent[]> getSpecificType() { |
| 1311 | + return WrappedChatComponent[].class; |
| 1312 | + } |
| 1313 | + } |
| 1314 | + |
| 1315 | + /** |
| 1316 | + * A delegated converter that supports NBT to Component Array and regular Component Array |
| 1317 | + * @author dmulloy2 |
| 1318 | + */ |
| 1319 | + private static class ComponentArrayConverter implements EquivalentConverter<WrappedChatComponent[]> { |
| 1320 | + private static final EquivalentConverter<WrappedChatComponent[]> DELEGATE; |
| 1321 | + static { |
| 1322 | + Class<?> packetClass = PacketType.Play.Server.UPDATE_SIGN.getPacketClass(); |
| 1323 | + if (packetClass.getName().contains("Sign")) { |
| 1324 | + DELEGATE = new LegacyComponentConverter(); |
| 1325 | + } else { |
| 1326 | + DELEGATE = new NBTComponentConverter(); |
| 1327 | + } |
| 1328 | + } |
| 1329 | + |
| 1330 | + @Override |
| 1331 | + public WrappedChatComponent[] getSpecific(Object generic) { |
| 1332 | + return DELEGATE.getSpecific(generic); |
| 1333 | + } |
| 1334 | + |
| 1335 | + @Override |
| 1336 | + public Object getGeneric(Class<?> genericType, WrappedChatComponent[] specific) { |
| 1337 | + return DELEGATE.getGeneric(genericType, specific); |
| 1338 | + } |
| 1339 | + |
| 1340 | + @Override |
| 1341 | + public Class<WrappedChatComponent[]> getSpecificType() { |
| 1342 | + return DELEGATE.getSpecificType(); |
| 1343 | + } |
| 1344 | + |
| 1345 | + public static Class<?> getGenericType() { |
| 1346 | + if (DELEGATE instanceof NBTComponentConverter) { |
| 1347 | + return MinecraftReflection.getNBTCompoundClass(); |
| 1348 | + } else { |
| 1349 | + return MinecraftReflection.getIChatBaseComponentArrayClass(); |
| 1350 | + } |
| 1351 | + } |
| 1352 | + } |
| 1353 | + |
1260 | 1354 | @Override
|
1261 | 1355 | public String toString() {
|
1262 | 1356 | return "PacketContainer[type=" + type + ", structureModifier=" + structureModifier + "]";
|
|
0 commit comments