|
1 | 1 | package net.earthcomputer.clientcommands.command.arguments; |
2 | 2 |
|
3 | 3 | import com.google.common.collect.ImmutableMap; |
| 4 | +import com.google.gson.JsonElement; |
| 5 | +import com.google.gson.JsonPrimitive; |
4 | 6 | import com.mojang.brigadier.StringReader; |
5 | 7 | import com.mojang.brigadier.arguments.ArgumentType; |
6 | 8 | import com.mojang.brigadier.context.CommandContext; |
7 | 9 | import com.mojang.brigadier.exceptions.CommandSyntaxException; |
| 10 | +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; |
8 | 11 | import com.mojang.brigadier.suggestion.Suggestions; |
9 | 12 | import com.mojang.brigadier.suggestion.SuggestionsBuilder; |
| 13 | +import com.mojang.serialization.JsonOps; |
| 14 | +import net.earthcomputer.clientcommands.mixin.HoverEventActionAccessor; |
10 | 15 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; |
11 | 16 | import net.minecraft.command.CommandSource; |
12 | | -import net.minecraft.text.*; |
| 17 | +import net.minecraft.text.ClickEvent; |
| 18 | +import net.minecraft.text.HoverEvent; |
| 19 | +import net.minecraft.text.MutableText; |
| 20 | +import net.minecraft.text.Style; |
| 21 | +import net.minecraft.text.Text; |
| 22 | +import net.minecraft.text.TextCodecs; |
| 23 | +import net.minecraft.text.TextColor; |
13 | 24 | import net.minecraft.util.Formatting; |
14 | 25 | import net.minecraft.util.Identifier; |
15 | | - |
16 | | -import java.util.*; |
| 26 | +import net.minecraft.util.StringIdentifiable; |
| 27 | +import net.minecraft.util.Util; |
| 28 | + |
| 29 | +import java.util.ArrayList; |
| 30 | +import java.util.Arrays; |
| 31 | +import java.util.Collection; |
| 32 | +import java.util.List; |
| 33 | +import java.util.Locale; |
| 34 | +import java.util.Map; |
17 | 35 | import java.util.concurrent.CompletableFuture; |
18 | | -import java.util.function.BiFunction; |
19 | 36 | import java.util.function.Consumer; |
| 37 | +import java.util.function.Function; |
20 | 38 |
|
21 | 39 | public class FormattedTextArgumentType implements ArgumentType<MutableText> { |
22 | | - |
23 | 40 | private static final Collection<String> EXAMPLES = Arrays.asList("Earth", "bold{xpple}", "bold{italic{red{nwex}}}"); |
| 41 | + private static final DynamicCommandExceptionType INVALID_CLICK_ACTION = new DynamicCommandExceptionType(action -> Text.translatable("commands.client.invalidClickAction", action)); |
| 42 | + private static final DynamicCommandExceptionType INVALID_HOVER_ACTION = new DynamicCommandExceptionType(action -> Text.translatable("commands.client.invalidHoverAction", action)); |
| 43 | + private static final DynamicCommandExceptionType INVALID_HOVER_EVENT = new DynamicCommandExceptionType(event -> Text.translatable("commands.client.invalidHoverEvent", event)); |
24 | 44 |
|
25 | 45 | private FormattedTextArgumentType() { |
26 | 46 | } |
@@ -177,28 +197,54 @@ static class FormattedText { |
177 | 197 | .put("hex", new Styler((s, o) -> s.withColor(TextColor.fromRgb(Integer.parseInt(o.get(0), 16))), 1)) |
178 | 198 | .put("insert", new Styler((s, o) -> s.withInsertion(o.get(0)), 1)) |
179 | 199 |
|
180 | | - .put("click", new Styler((s, o) -> s.withClickEvent(new ClickEvent(ClickEvent.Action.byName(o.get(0)), o.get(1))), 2, "change_page", "copy_to_clipboard", "open_file", "open_url", "run_command", "suggest_command")) |
181 | | - .put("hover", new Styler((s, o) -> s.withHoverEvent(HoverEvent.Action.byName(o.get(0)).buildHoverEvent(Text.of(o.get(1)))), 2, "show_entity", "show_item", "show_text")) |
| 200 | + .put("click", new Styler((s, o) -> s.withClickEvent(parseClickEvent(o.get(0), o.get(1))), 2, "change_page", "copy_to_clipboard", "open_file", "open_url", "run_command", "suggest_command")) |
| 201 | + .put("hover", new Styler((s, o) -> s.withHoverEvent(parseHoverEvent(o.get(0), o.get(1))), 2, "show_entity", "show_item", "show_text")) |
182 | 202 |
|
183 | 203 | // aliases |
184 | 204 | .put("strike", new Styler((s, o) -> s.withFormatting(Formatting.STRIKETHROUGH), 0)) |
185 | 205 | .put("magic", new Styler((s, o) -> s.withFormatting(Formatting.OBFUSCATED), 0)) |
186 | 206 | .build(); |
187 | 207 |
|
188 | | - private final BiFunction<Style, List<String>, Style> styler; |
| 208 | + private final StylerFunc styler; |
189 | 209 | private final MutableText argument; |
190 | | - private final List<String> optional; |
| 210 | + private final List<String> args; |
191 | 211 |
|
192 | | - public FormattedText(BiFunction<Style, List<String>, Style> styler, MutableText argument, List<String> optional) { |
| 212 | + public FormattedText(StylerFunc styler, MutableText argument, List<String> args) { |
193 | 213 | this.styler = styler; |
194 | 214 | this.argument = argument; |
195 | | - this.optional = optional; |
| 215 | + this.args = args; |
| 216 | + } |
| 217 | + |
| 218 | + public MutableText style() throws CommandSyntaxException { |
| 219 | + return this.argument.setStyle(this.styler.apply(this.argument.getStyle(), this.args)); |
| 220 | + } |
| 221 | + |
| 222 | + private record Styler(StylerFunc operator, int argumentCount, String... suggestions) {} |
| 223 | + |
| 224 | + @FunctionalInterface |
| 225 | + interface StylerFunc { |
| 226 | + Style apply(Style style, List<String> args) throws CommandSyntaxException; |
196 | 227 | } |
197 | 228 |
|
198 | | - public MutableText style() { |
199 | | - return this.argument.setStyle(this.styler.apply(this.argument.getStyle(), this.optional)); |
| 229 | + private static final Function<String, ClickEvent.Action> CLICK_EVENT_ACTION_BY_NAME = StringIdentifiable.createMapper(ClickEvent.Action.values(), Function.identity()); |
| 230 | + |
| 231 | + private static ClickEvent parseClickEvent(String name, String value) throws CommandSyntaxException { |
| 232 | + ClickEvent.Action action = CLICK_EVENT_ACTION_BY_NAME.apply(name); |
| 233 | + if (action == null) { |
| 234 | + throw INVALID_CLICK_ACTION.create(name); |
| 235 | + } |
| 236 | + return new ClickEvent(action, value); |
200 | 237 | } |
201 | 238 |
|
202 | | - private record Styler(BiFunction<Style, List<String>, Style> operator, int argumentCount, String... suggestions) {} |
| 239 | + private static HoverEvent parseHoverEvent(String name, String value) throws CommandSyntaxException { |
| 240 | + HoverEvent.Action<?> action = HoverEvent.Action.UNVALIDATED_CODEC.parse(JsonOps.INSTANCE, new JsonPrimitive(name)).result().orElse(null); |
| 241 | + if (action == null) { |
| 242 | + throw INVALID_HOVER_ACTION.create(name); |
| 243 | + } |
| 244 | + |
| 245 | + JsonElement text = Util.getResult(TextCodecs.CODEC.encodeStart(JsonOps.INSTANCE, Text.of(value)), IllegalStateException::new); |
| 246 | + HoverEvent.EventData<?> eventData = Util.getResult(((HoverEventActionAccessor) action).getLegacyCodec().parse(JsonOps.INSTANCE, text), error -> INVALID_HOVER_EVENT.create(value)); |
| 247 | + return new HoverEvent(eventData); |
| 248 | + } |
203 | 249 | } |
204 | 250 | } |
0 commit comments