From 2070dcb9581e67c2dae162f6be2829b566fd9d94 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Thu, 1 Aug 2024 17:53:13 -0700 Subject: [PATCH] Allow platforms to override ComponentMessageThrowable conversions We don't use ServiceLoader as that would require other workarounds on NeoForge (the target for this change), due to non-'GAMELIBRARY's not being able to discover game-aware service implementations. --- .../extras/MinecraftExceptionHandler.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/cloud-minecraft-extras/src/main/java/org/incendo/cloud/minecraft/extras/MinecraftExceptionHandler.java b/cloud-minecraft-extras/src/main/java/org/incendo/cloud/minecraft/extras/MinecraftExceptionHandler.java index 6cef32a4..2fdca540 100644 --- a/cloud-minecraft-extras/src/main/java/org/incendo/cloud/minecraft/extras/MinecraftExceptionHandler.java +++ b/cloud-minecraft-extras/src/main/java/org/incendo/cloud/minecraft/extras/MinecraftExceptionHandler.java @@ -437,7 +437,9 @@ private static Component getMessage(final ComponentCaptionFormatter forma if (throwable instanceof ParserException) { return ((ParserException) throwable).formatCaption(formatter); } - final Component msg = ComponentMessageThrowable.getOrConvertMessage(throwable); + final Component msg = ComponentMessageThrowable.getOrConvertMessage( + ComponentMessageThrowableConverterHolder.instance.maybeConvert(throwable) + ); return msg == null ? NULL : msg; } @@ -472,4 +474,45 @@ public interface Decorator { @NonNull Component message ); } + + /** + * Converts Throwables to ComponentMessageThrowables when possible. + */ + @API(status = API.Status.INTERNAL) + @FunctionalInterface + public interface ComponentMessageThrowableConverter { + /** + * Converts a Throwable to a ComponentMessageThrowable if possible. + * + * @param thr throwable + * @return possibly converted throwable + */ + Throwable maybeConvert(Throwable thr); + } + + /** + * Default implementation and holder for {@link ComponentMessageThrowableConverter}. + */ + @API(status = API.Status.INTERNAL) + public static final class ComponentMessageThrowableConverterHolder implements ComponentMessageThrowableConverter { + private static ComponentMessageThrowableConverter instance = new ComponentMessageThrowableConverterHolder(); + + /** + * Replaces the converter. Mainly useful for platforms that need custom logic to transform vanilla CommandSyntaxExceptions + * into an Adventure representation. + * + * @param converter converter + */ + public static void converter(final ComponentMessageThrowableConverter converter) { + instance = Objects.requireNonNull(converter, "converter"); + } + + private ComponentMessageThrowableConverterHolder() { + } + + @Override + public Throwable maybeConvert(final Throwable thr) { + return thr; + } + } }