3535import com .google .gson .JsonElement ;
3636import com .google .gson .JsonObject ;
3737import com .google .gson .JsonPrimitive ;
38+ import com .google .gson .internal .LazilyParsedNumber ;
3839import com .viaversion .viaversion .api .Via ;
3940import com .viaversion .viaversion .api .connection .UserConnection ;
4041import com .viaversion .viaversion .api .data .MappingData ;
6566import com .viaversion .viaversion .rewriter .SoundRewriter ;
6667import com .viaversion .viaversion .rewriter .StatisticsRewriter ;
6768import com .viaversion .viaversion .rewriter .TagRewriter ;
69+ import java .nio .charset .StandardCharsets ;
6870import java .util .Arrays ;
6971import java .util .BitSet ;
7072import java .util .HashSet ;
@@ -264,7 +266,12 @@ protected void registerPackets() {
264266 registerClientbound (ClientboundPackets1_20_2 .ACTIONBAR , this ::convertComponent );
265267 registerClientbound (ClientboundPackets1_20_2 .TITLE_TEXT , this ::convertComponent );
266268 registerClientbound (ClientboundPackets1_20_2 .TITLE_SUBTITLE , this ::convertComponent );
267- registerClientbound (ClientboundPackets1_20_2 .DISGUISED_CHAT , this ::convertComponent );
269+ registerClientbound (ClientboundPackets1_20_2 .DISGUISED_CHAT , wrapper -> {
270+ convertComponent (wrapper );
271+ wrapper .passthrough (Type .VAR_INT ); // Chat type
272+ convertComponent (wrapper ); // Name
273+ convertOptionalComponent (wrapper ); // Target name
274+ });
268275 registerClientbound (ClientboundPackets1_20_2 .SYSTEM_CHAT , this ::convertComponent );
269276 registerClientbound (ClientboundPackets1_20_2 .OPEN_WINDOW , wrapper -> {
270277 wrapper .passthrough (Type .VAR_INT ); // Container id
@@ -326,7 +333,7 @@ public void register() {
326333 registerClientbound (State .CONFIGURATION , ClientboundConfigurationPackets1_20_2 .RESOURCE_PACK .getId (), ClientboundConfigurationPackets1_20_3 .RESOURCE_PACK_PUSH .getId (), resourcePackHandler (ClientboundConfigurationPackets1_20_3 .RESOURCE_PACK_POP ));
327334 // TODO Auto map via packet types provider
328335 registerClientbound (State .CONFIGURATION , ClientboundConfigurationPackets1_20_2 .UPDATE_ENABLED_FEATURES .getId (), ClientboundConfigurationPackets1_20_3 .UPDATE_ENABLED_FEATURES .getId ());
329- registerClientbound (State .CONFIGURATION , ClientboundConfigurationPackets1_20_2 .UPDATE_TAGS .getId (), ClientboundConfigurationPackets1_20_3 .UPDATE_TAGS .getId ());
336+ registerClientbound (State .CONFIGURATION , ClientboundConfigurationPackets1_20_2 .UPDATE_TAGS .getId (), ClientboundConfigurationPackets1_20_3 .UPDATE_TAGS .getId (), tagRewriter . getGenericHandler () );
330337 }
331338
332339 private PacketHandler resourcePackStatusHandler () {
@@ -346,16 +353,19 @@ private PacketHandler resourcePackStatusHandler() {
346353
347354 private PacketHandler resourcePackHandler (final ClientboundPacketType popType ) {
348355 return wrapper -> {
349- wrapper .write (Type .UUID , UUID .randomUUID ());
350- wrapper .passthrough (Type .STRING ); // Url
351- wrapper .passthrough (Type .STRING ); // Hash
352- wrapper .passthrough (Type .BOOLEAN ); // Required
353- convertOptionalComponent (wrapper );
354-
355356 // Drop old resource packs first
356357 final PacketWrapper dropPacksPacket = wrapper .create (popType );
357358 dropPacksPacket .write (Type .OPTIONAL_UUID , null );
358359 dropPacksPacket .send (Protocol1_20_3To1_20_2 .class );
360+
361+ // Use the hash to write a pack uuid
362+ final String url = wrapper .read (Type .STRING );
363+ final String hash = wrapper .read (Type .STRING );
364+ wrapper .write (Type .UUID , UUID .nameUUIDFromBytes (hash .getBytes (StandardCharsets .UTF_8 )));
365+ wrapper .write (Type .STRING , url );
366+ wrapper .write (Type .STRING , hash );
367+ wrapper .passthrough (Type .BOOLEAN ); // Required
368+ convertOptionalComponent (wrapper );
359369 };
360370 }
361371
@@ -390,10 +400,12 @@ private void convertOptionalComponent(final PacketWrapper wrapper) throws Except
390400 return null ;
391401 } else if (element .isJsonObject ()) {
392402 final CompoundTag tag = new CompoundTag ();
393- for ( final Map . Entry < String , JsonElement > entry : element .getAsJsonObject (). entrySet ()) {
394- // Not strictly needed, but might as well make it more compact
403+ final JsonObject jsonObject = element .getAsJsonObject ();
404+ for ( final Map . Entry < String , JsonElement > entry : jsonObject . entrySet ()) {
395405 convertObjectEntry (entry .getKey (), entry .getValue (), tag );
396406 }
407+
408+ addComponentType (jsonObject , tag );
397409 return tag ;
398410 } else if (element .isJsonArray ()) {
399411 return convertJsonArray (element );
@@ -418,12 +430,37 @@ private void convertOptionalComponent(final PacketWrapper wrapper) throws Except
418430 return new DoubleTag (number .doubleValue ());
419431 } else if (number instanceof Float ) {
420432 return new FloatTag (number .floatValue ());
433+ } else if (number instanceof LazilyParsedNumber ) {
434+ // TODO: This might need better handling
435+ return new IntTag (number .intValue ());
421436 }
422- return new StringTag ( primitive . getAsString ()); // ???
437+ return new IntTag ( number . intValue ()); // ???
423438 }
424439 throw new IllegalArgumentException ("Unhandled json type " + element .getClass ().getSimpleName () + " with value " + element .getAsString ());
425440 }
426441
442+ private static void addComponentType (final JsonObject object , final CompoundTag tag ) {
443+ if (object .has ("type" )) {
444+ return ;
445+ }
446+
447+ // Add the type to speed up deserialization and make DFU errors slightly more useful
448+ // Order is important
449+ if (object .has ("text" )) {
450+ tag .put ("type" , new StringTag ("text" ));
451+ } else if (object .has ("translate" )) {
452+ tag .put ("type" , new StringTag ("translatable" ));
453+ } else if (object .has ("score" )) {
454+ tag .put ("type" , new StringTag ("score" ));
455+ } else if (object .has ("selector" )) {
456+ tag .put ("type" , new StringTag ("selector" ));
457+ } else if (object .has ("keybind" )) {
458+ tag .put ("type" , new StringTag ("keybind" ));
459+ } else if (object .has ("nbt" )) {
460+ tag .put ("type" , new StringTag ("nbt" ));
461+ }
462+ }
463+
427464 private static ListTag convertJsonArray (final JsonElement element ) {
428465 // TODO Number arrays?
429466 final ListTag listTag = new ListTag ();
@@ -454,29 +491,38 @@ private static ListTag convertJsonArray(final JsonElement element) {
454491
455492 // Wrap all entries in compound tags as lists can only consist of one type of tag
456493 final CompoundTag compoundTag = new CompoundTag ();
494+ compoundTag .put ("type" , new StringTag ("text" ));
457495 compoundTag .put ("text" , new StringTag ());
458496 compoundTag .put ("extra" , convertedTag );
459497 }
460498 return processedListTag ;
461499 }
462500
463- private static void convertObjectEntry (final String key , final JsonElement element , final CompoundTag tag ) {
464- if ((key .equals ("contents" )) && element .isJsonObject ()) {
501+ /**
502+ * Converts a json object entry to a tag entry.
503+ *
504+ * @param key key of the entry
505+ * @param value value of the entry
506+ * @param tag the resulting compound tag
507+ */
508+ private static void convertObjectEntry (final String key , final JsonElement value , final CompoundTag tag ) {
509+ if ((key .equals ("contents" )) && value .isJsonObject ()) {
465510 // Store show_entity id as int array instead of uuid string
466- final JsonObject hoverEvent = element .getAsJsonObject ();
511+ // Not really required, but we might as well make it more compact
512+ final JsonObject hoverEvent = value .getAsJsonObject ();
467513 final JsonElement id = hoverEvent .get ("id" );
468514 final UUID uuid ;
469515 if (id != null && id .isJsonPrimitive () && (uuid = parseUUID (id .getAsString ())) != null ) {
470516 hoverEvent .remove ("id" );
471517
472- final CompoundTag convertedTag = (CompoundTag ) convertToTag (element );
518+ final CompoundTag convertedTag = (CompoundTag ) convertToTag (value );
473519 convertedTag .put ("id" , new IntArrayTag (UUIDIntArrayType .uuidToIntArray (uuid )));
474520 tag .put (key , convertedTag );
475521 return ;
476522 }
477523 }
478524
479- tag .put (key , convertToTag (element ));
525+ tag .put (key , convertToTag (value ));
480526 }
481527
482528 private static @ Nullable UUID parseUUID (final String uuidString ) {
0 commit comments