KyoriPowered / adventure

A user-interface library, formerly known as text, for Minecraft: Java Edition
https://docs.advntr.dev/
MIT License
679 stars 105 forks source link

`ComponentFlattener.basic()` converts `ScoreComponent` with null `value` to null #953

Closed Konicai closed 11 months ago

Konicai commented 11 months ago

A specific action bar received by Geyser cannot be serialized using the legacy serializer. The offending component was logged to console by the reporting user:

{"extra":[{"extra":[{"font":"nameplates:default","text":"끎끓끒끑끗"},{"color":"red","extra":[{"font":"nameplates:default","text":"끎끓끒끑끐끏끗"},{"color":"#00A5FF","extra":[{"font":"nameplates:default","text":"끎끔끑끏끗"},{"color":"#D31FEB","extra":[{"font":"nameplates:default","text":"끎끓끒끐끗"},{"color":"green","extra":[{"font":"nameplates:default","text":""},{"color":"#FFFEFD","extra":[{"font":"nameplates:ascent_-5","text":"100"},{"text":" "},{"font":"nameplates:default","text":"뀅"}],"text":""}],"text":"44°C   "}],"text":"20.0 ✦   "}],"text":"1.0 ❈   "}],"text":"20 ❤   "}],"text":""}],"score":{"name":"nameplates","objective":"actionbar"}}

I was able to reproduce the issue and have posted it a test project here:

    @Test
    public void testThing() {
        String input = "{\"extra\":[{\"extra\":[{\"font\":\"nameplates:default\",\"text\":\"끎\uF801끓\uF801끒\uF801끑\uF801끗\uF809\uF808\uF803\"},{\"color\":\"red\",\"extra\":[{\"font\":\"nameplates:default\",\"text\":\"끎\uF801끓\uF801끒\uF801끑\uF801끐\uF801끏\uF801끗\uF809\uF808\uF806\"},{\"color\":\"#00A5FF\",\"extra\":[{\"font\":\"nameplates:default\",\"text\":\"끎\uF801끔\uF801끑\uF801끏\uF801끗\uF80A\uF804\"},{\"color\":\"#D31FEB\",\"extra\":[{\"font\":\"nameplates:default\",\"text\":\"끎\uF801끓\uF801끒\uF801끐\uF801끗\uF809\uF808\uF801\"},{\"color\":\"green\",\"extra\":[{\"font\":\"nameplates:default\",\"text\":\"\uF819\uF818\uF813\"},{\"color\":\"#FFFEFD\",\"extra\":[{\"font\":\"nameplates:ascent_-5\",\"text\":\"100\"},{\"text\":\" \"},{\"font\":\"nameplates:default\",\"text\":\"뀅\"}],\"text\":\"\"}],\"text\":\"44°C   \uF80A\uF809\uF804\"}],\"text\":\"20.0 ✦   \"}],\"text\":\"1.0 ❈   \"}],\"text\":\"20 ❤   \"}],\"text\":\"\uF828\uF824\"}],\"score\":{\"name\":\"nameplates\",\"objective\":\"actionbar\"}}";
        Component message = GsonComponentSerializer.gson().deserialize(input);
        System.out.println(PlainTextComponentSerializer.plainText().serialize(message));
        LegacyComponentSerializer.legacySection().serialize(message);
    }

The following error occurs while trying to serialize the component to legacy text:

Cannot invoke "String.isEmpty()" because "text" is null
java.lang.NullPointerException: Cannot invoke "String.isEmpty()" because "text" is null
    at net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializerImpl$Cereal.component(LegacyComponentSerializerImpl.java:326)
    at net.kyori.adventure.text.flattener.ComponentFlattenerImpl.lambda$flattener$3(ComponentFlattenerImpl.java:117)
    at net.kyori.adventure.text.flattener.ComponentFlattenerImpl.flatten0(ComponentFlattenerImpl.java:95)
    at net.kyori.adventure.text.flattener.ComponentFlattenerImpl.flatten(ComponentFlattenerImpl.java:78)
    at net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializerImpl.serialize(LegacyComponentSerializerImpl.java:271)
    at me.konicai.test.ActionBarTest.testThing(ActionBarTest.java:18)

The plain text serializer works fine and creates the following output (null at the front seems smelly):

null끎끓끒끑끗20 ❤   끎끓끒끑끐끏끗1.0 ❈   끎끔끑끏끗20.0 ✦   끎끓끒끐끗44°C   100 뀅

This occurs with 4.14.0, which the test project is running (unlike Geyser). The affected code in Geyser begins here.