diff --git a/src/main/java/net/neoforged/neoforge/server/command/TagsCommand.java b/src/main/java/net/neoforged/neoforge/server/command/TagsCommand.java index 38091a87ac..8645cc8733 100644 --- a/src/main/java/net/neoforged/neoforge/server/command/TagsCommand.java +++ b/src/main/java/net/neoforged/neoforge/server/command/TagsCommand.java @@ -11,9 +11,9 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import java.util.Iterator; import java.util.Optional; import java.util.function.Supplier; -import java.util.stream.Collectors; import java.util.stream.Stream; import net.minecraft.ChatFormatting; import net.minecraft.commands.CommandSourceStack; @@ -51,6 +51,10 @@ * */ class TagsCommand { + // The limit of how long the clipboard text can be; no more elements are added to the text if they would push it over this limit + // This is roughly below 32767, the default limit for UTF-8 strings in FriendlyByteBuf. When adjusting this, make sure to leave + // ample room for the explanatory text (see #createMessage() below). + private static final long CLIPBOARD_TEXT_LIMIT = 32600; private static final long PAGE_SIZE = 8; private static final ResourceKey>> ROOT_REGISTRY_KEY = ResourceKey.createRegistryKey(ResourceLocation.withDefaultNamespace("root")); @@ -171,16 +175,45 @@ private static MutableComponent createMessage(final MutableComponent header, final long currentPage, final ChatFormatting elementColor, final Supplier> names) { - final String allElementNames = names.get().sorted().collect(Collectors.joining("\n")); final long totalPages = (count - 1) / PAGE_SIZE + 1; final long actualPage = (long) Mth.clamp(currentPage, 1, totalPages); MutableComponent containsComponent = Component.translatable(containsText, count); if (count > 0) // Highlight the count text, make it clickable, and append page counters { + final String clipboardText; + final StringBuilder clipboardTextBuilder = new StringBuilder(); + boolean reachedLimit = false; + int countedLines = 0; + + Iterator iterator = names.get().sorted().iterator(); + while (iterator.hasNext()) { + final String line = iterator.next(); + if (clipboardTextBuilder.length() + line.length() > CLIPBOARD_TEXT_LIMIT) { + // The to-be-added line puts us over the limit, so stop adding lines + reachedLimit = true; + break; + } + clipboardTextBuilder.append(line).append('\n'); + countedLines++; + } + // Remove the trailing newline if present + if (!clipboardTextBuilder.isEmpty()) { + clipboardTextBuilder.deleteCharAt(clipboardTextBuilder.length() - 1); + } + + if (reachedLimit) { + // Almost went over the limit; add additional info to clipboard text + clipboardText = "(Too many entries to fit in clipboard, showing only first " + countedLines + " entries...)" + '\n' + + clipboardTextBuilder + '\n' + + "(..." + (count - countedLines) + " more entries not shown)"; + } else { + clipboardText = clipboardTextBuilder.toString(); + } + containsComponent = ComponentUtils.wrapInSquareBrackets(containsComponent.withStyle(s -> s .withColor(ChatFormatting.GREEN) - .withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, allElementNames)) + .withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, clipboardText)) .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable(copyHoverText))))); containsComponent = Component.translatable("commands.neoforge.tags.page_info",