diff --git a/patches/server/0018-Better-handling-of-invalid-JSON-components.patch b/patches/server/0018-Better-handling-of-invalid-JSON-components.patch new file mode 100644 index 0000000..2c59825 --- /dev/null +++ b/patches/server/0018-Better-handling-of-invalid-JSON-components.patch @@ -0,0 +1,199 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Video +Date: Mon, 28 Mar 2022 13:19:43 -0600 +Subject: [PATCH] Better handling of invalid JSON components + + +diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java +index 5ba1636bbb938373e43c1f3ac561368fc9cffd43..6978d14c6bd90ffb640e39e8666430d95d5ef45c 100644 +--- a/src/main/java/net/minecraft/network/chat/Component.java ++++ b/src/main/java/net/minecraft/network/chat/Component.java +@@ -24,6 +24,8 @@ import java.util.List; + import java.util.Map.Entry; + import java.util.Optional; + import javax.annotation.Nullable; ++ ++import net.minecraft.ChatFormatting; + import net.minecraft.Util; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.util.FormattedCharSequence; +@@ -427,6 +429,26 @@ public interface Component extends Message, FormattedText, Iterable { + return Component.Serializer.GSON.toJsonTree(text); + } + ++ // Scissors start ++ @Nullable ++ public static MutableComponent fromJsonSafe(String json) { ++ try { ++ return fromJson(json); ++ } catch (Exception ex) { ++ return new TextComponent("** Invalid JSON Component **").withStyle(ChatFormatting.RED); ++ } ++ } ++ ++ @Nullable ++ public static MutableComponent fromJsonSafe(JsonElement json) { ++ try { ++ return fromJson(json); ++ } catch (Exception ex) { ++ return new TextComponent("** Invalid JSON Component **").withStyle(ChatFormatting.RED); ++ } ++ } ++ // Scissors end ++ + @Nullable + public static MutableComponent fromJson(String json) { + return (MutableComponent) GsonHelper.fromJson(Component.Serializer.GSON, json, MutableComponent.class, false); +diff --git a/src/main/java/net/minecraft/network/chat/HoverEvent.java b/src/main/java/net/minecraft/network/chat/HoverEvent.java +index 9c1341803cf892f7f3af11381bd56bc95f31fad0..c4394812326bccd70d64b4bd45eb1bb7b53b0905 100644 +--- a/src/main/java/net/minecraft/network/chat/HoverEvent.java ++++ b/src/main/java/net/minecraft/network/chat/HoverEvent.java +@@ -80,7 +80,7 @@ public class HoverEvent { + if (jsonElement != null) { + return action.deserialize(jsonElement); + } else { +- Component component = Component.Serializer.fromJson(json.get("value")); ++ Component component = Component.Serializer.fromJsonSafe(json.get("value")); // Scissors - Use safer method for getting Components from JSON + return component != null ? action.deserializeFromLegacy(component) : null; + } + } +@@ -95,7 +95,7 @@ public class HoverEvent { + } + + public static class Action { +- public static final HoverEvent.Action SHOW_TEXT = new HoverEvent.Action<>("show_text", true, Component.Serializer::fromJson, Component.Serializer::toJsonTree, Function.identity()); ++ public static final HoverEvent.Action SHOW_TEXT = new HoverEvent.Action<>("show_text", true, Component.Serializer::fromJsonSafe, Component.Serializer::toJsonTree, Function.identity()); // Scissors - Use safer method for getting Components from JSON + public static final HoverEvent.Action SHOW_ITEM = new HoverEvent.Action<>("show_item", true, HoverEvent.ItemStackInfo::create, HoverEvent.ItemStackInfo::serialize, HoverEvent.ItemStackInfo::create); + public static final HoverEvent.Action SHOW_ENTITY = new HoverEvent.Action<>("show_entity", true, HoverEvent.EntityTooltipInfo::create, HoverEvent.EntityTooltipInfo::serialize, HoverEvent.EntityTooltipInfo::create); + private static final Map> LOOKUP = Stream.of(SHOW_TEXT, SHOW_ITEM, SHOW_ENTITY).collect(ImmutableMap.toImmutableMap(HoverEvent.Action::getName, (action) -> { +@@ -183,7 +183,7 @@ public class HoverEvent { + return null; + } + // Scissors end +- Component component = Component.Serializer.fromJson(jsonObject.get("name")); ++ Component component = Component.Serializer.fromJsonSafe(jsonObject.get("name")); // Scissors - Use safer method for getting Components from JSON + return new HoverEvent.EntityTooltipInfo(entityType, uUID, component); + } + } +@@ -192,7 +192,7 @@ public class HoverEvent { + public static HoverEvent.EntityTooltipInfo create(Component text) { + try { + CompoundTag compoundTag = TagParser.parseTag(text.getString()); +- Component component = Component.Serializer.fromJson(compoundTag.getString("name")); ++ Component component = Component.Serializer.fromJsonSafe(compoundTag.getString("name")); // Scissors - Use safer method for getting Components from JSON + EntityType entityType = Registry.ENTITY_TYPE.get(new ResourceLocation(compoundTag.getString("type"))); + // Scissors start + UUID uUID; +diff --git a/src/main/java/net/minecraft/network/chat/NbtComponent.java b/src/main/java/net/minecraft/network/chat/NbtComponent.java +index ae9fef071388bc6b10d34a0126c9dd1ac77eb9e7..f5f2ec1192303bc55a64dce3e0457e4531a35ba7 100644 +--- a/src/main/java/net/minecraft/network/chat/NbtComponent.java ++++ b/src/main/java/net/minecraft/network/chat/NbtComponent.java +@@ -77,13 +77,14 @@ public abstract class NbtComponent extends BaseComponent implements ContextAware + if (this.interpreting) { + Component component = DataFixUtils.orElse(ComponentUtils.updateForEntity(source, this.separator, sender, depth), ComponentUtils.DEFAULT_NO_STYLE_SEPARATOR); + return stream.flatMap((text) -> { ++ // Scissors start - Use safer method for getting Components from JSON + try { +- MutableComponent mutableComponent = Component.Serializer.fromJson(text); ++ MutableComponent mutableComponent = Component.Serializer.fromJsonSafe(text); + return Stream.of(ComponentUtils.updateForEntity(source, mutableComponent, sender, depth)); + } catch (Exception var5) { +- LOGGER.warn("Failed to parse component: {}", text, var5); + return Stream.of(); + } ++ // Scissors end + }).reduce((accumulator, current) -> { + return accumulator.append(component).append(current); + }).orElseGet(() -> { +@@ -94,7 +95,7 @@ public abstract class NbtComponent extends BaseComponent implements ContextAware + return stream.map((string) -> { + return new TextComponent(string); + }).reduce((accumulator, current) -> { +- return accumulator.append(text).append(current); ++ return (TextComponent) accumulator.append(text).append(current); + }).orElseGet(() -> { + return new TextComponent(""); + }); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index b7c4700fd5db14c77e7ee78311dd77a754d9d41c..07f04c1708b118ace3ed73ae2bf88c29b1c80ad2 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2202,12 +2202,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + this.setRot(this.getYRot(), this.getXRot()); + if (nbt.contains("CustomName", 8)) { + String s = nbt.getString("CustomName"); +- +- try { +- this.setCustomName(Component.Serializer.fromJson(s)); +- } catch (Exception exception) { +- Entity.LOGGER.warn("Failed to parse entity custom name {}", s, exception); +- } ++ this.setCustomName(Component.Serializer.fromJsonSafe(s)); // Scissors - Use safer method for getting Components from JSON + } + + this.setCustomNameVisible(nbt.getBoolean("CustomNameVisible")); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +index 3281448bf37da8a1b4b7b44f10f4b2438b4a4f29..8038e3a10b563321df1e8cedd26b256078ce745a 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -405,7 +405,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + this.levels = nbt.getInt("Levels"); // SPIGOT-5053, use where available + // CraftBukkit end + if (nbt.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(nbt.getString("CustomName")); ++ this.name = Component.Serializer.fromJsonSafe(nbt.getString("CustomName")); // Scissors - Use safer method for getting Components from JSON + } + + this.lockKey = LockCode.fromTag(nbt); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java +index 40ac65501a0213b43964fd68eb155d4358fb7fd4..9cfc44472e841e1a2cd7de2a1284afdde05a7989 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java +@@ -44,7 +44,7 @@ public class EnchantmentTableBlockEntity extends BlockEntity implements Nameable + public void load(CompoundTag nbt) { + super.load(nbt); + if (nbt.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(nbt.getString("CustomName")); ++ this.name = Component.Serializer.fromJsonSafe(nbt.getString("CustomName")); // Scissors - Use safer method for getting Components from JSON + } + + } +diff --git a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java +index 2153e7035535990b5307b85d8bc3dab50c0a3ae8..5f11f9b77684bd91b4cfe77cd415ed42bd9bc21a 100644 +--- a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java ++++ b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java +@@ -39,7 +39,7 @@ public class ScoreboardSaveData extends SavedData { + } + + PlayerTeam playerTeam = this.scoreboard.addPlayerTeam(string); +- Component component = Component.Serializer.fromJson(compoundTag.getString("DisplayName")); ++ Component component = Component.Serializer.fromJsonSafe(compoundTag.getString("DisplayName")); // Scissors - Use safer method for getting Components from JSON + if (component != null) { + playerTeam.setDisplayName(component); + } +@@ -57,14 +57,14 @@ public class ScoreboardSaveData extends SavedData { + } + + if (compoundTag.contains("MemberNamePrefix", 8)) { +- Component component2 = Component.Serializer.fromJson(compoundTag.getString("MemberNamePrefix")); ++ Component component2 = Component.Serializer.fromJsonSafe(compoundTag.getString("MemberNamePrefix")); // Scissors - Use safer method for getting Components from JSON + if (component2 != null) { + playerTeam.setPlayerPrefix(component2); + } + } + + if (compoundTag.contains("MemberNameSuffix", 8)) { +- Component component3 = Component.Serializer.fromJson(compoundTag.getString("MemberNameSuffix")); ++ Component component3 = Component.Serializer.fromJsonSafe(compoundTag.getString("MemberNameSuffix")); // Scissors - Use safer method for getting Components from JSON + if (component3 != null) { + playerTeam.setPlayerSuffix(component3); + } +@@ -123,7 +123,7 @@ public class ScoreboardSaveData extends SavedData { + string = string.substring(0, 16); + } + +- Component component = Component.Serializer.fromJson(compoundTag.getString("DisplayName")); ++ Component component = Component.Serializer.fromJsonSafe(compoundTag.getString("DisplayName")); // Scissors - Use safer method for getting Components from JSON + ObjectiveCriteria.RenderType renderType = ObjectiveCriteria.RenderType.byId(compoundTag.getString("RenderType")); + this.scoreboard.addObjective(string, objectiveCriteria, component, renderType); + });