Repository: kyoripowered/adventure
Issue: `ComponentFlattener.basic()` converts `ScoreComponent` with null `value` to null

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](https://github.com/Konicai/actionbar-test/blob/main/src/test/java/me/konicai/test/ActionBarTest.java):
```java
    @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](https://github.com/GeyserMC/Geyser/blob/18e7db8c30821edf38410d91e13d1a3690eff066/core/src/main/java/org/geysermc/geyser/translator/protocol/java/title/JavaSetActionBarTextTranslator.java#L44).

Changed files:
api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattenerImpl.java

diff --git a/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattenerImpl.java b/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattenerImpl.java
index 78dce1c1..51c1987b 100644
--- a/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattenerImpl.java
+++ b/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattenerImpl.java
@@ -47,7 +47,11 @@ final class ComponentFlattenerImpl implements ComponentFlattener {
   @SuppressWarnings("deprecation")
   static final ComponentFlattener BASIC = new BuilderImpl()
     .mapper(KeybindComponent.class, component -> component.keybind()) // IntelliJ is wrong here, this is fine
-    .mapper(ScoreComponent.class, ScoreComponent::value) // Removed in Vanilla 1.16, but we keep it for backwards compat
+    .mapper(ScoreComponent.class, component -> {
+      // Removed in Vanilla 1.16, but we keep it for backwards compat
+      final @Nullable String value = component.value();
+      return value != null ? value : "";
+    })
     .mapper(SelectorComponent.class, SelectorComponent::pattern)
     .mapper(TextComponent.class, TextComponent::content)
     .mapper(TranslatableComponent.class, component -> {