From 26c42cc59c48e274c4cddefd5d18397ac990bc82 Mon Sep 17 00:00:00 2001 From: m1Riss <3081974632@qq.com> Date: Thu, 28 May 2026 23:45:50 +0800 Subject: [PATCH 1/5] feat(ctnh-lib): add /ctnh hand and /ctnh showtag inspection commands --- .../command/CTNHCommandChatHelper.java | 105 ++++++++ .../ctnhlib/command/CTNHCommandInspector.java | 233 +++++++++++++++++ .../mcmod/ctnhlib/command/CTNHCommands.java | 234 ++++++++++++++++++ .../mcmod/ctnhlib/common/CommonProxy.java | 10 + .../resources/assets/ctnhlib/lang/en_us.json | 29 +++ .../resources/assets/ctnhlib/lang/zh_cn.json | 29 +++ 6 files changed, 640 insertions(+) create mode 100644 src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java create mode 100644 src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandInspector.java create mode 100644 src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java create mode 100644 src/main/resources/assets/ctnhlib/lang/en_us.json create mode 100644 src/main/resources/assets/ctnhlib/lang/zh_cn.json diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java new file mode 100644 index 0000000..b16f0aa --- /dev/null +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java @@ -0,0 +1,105 @@ +package tech.vixhentx.mcmod.ctnhlib.command; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Style; + +import java.util.ArrayList; +import java.util.List; + +/** + * Helpers for building click-to-copy chat lines used by /ctnh inspection commands. + * Each emitted line copies the full "label: value" text on click and shows a hover tooltip. + */ +public final class CTNHCommandChatHelper { + + /** Maximum length of a single chat line value before it is split into chunks. */ + public static final int MAX_VALUE_LINE_LENGTH = 256; + + private CTNHCommandChatHelper() {} + + /** + * Build one or more clickable chat lines for a labeled value. Long values are split into + * additional copyable continuation lines so chat does not silently drop content. + * + * @param label localized label + * @param value raw value string (must not be null) + * @return one or more {@link Component} lines ready to be sent + */ + public static List labeledLines(Component label, String value) { + List lines = new ArrayList<>(); + String safe = value == null ? "" : value; + String labelText = label.getString(); + if (safe.length() <= MAX_VALUE_LINE_LENGTH) { + lines.add(buildLine(label, safe, labelText + ": " + safe)); + return lines; + } + int total = safe.length(); + int chunkIndex = 0; + for (int start = 0; start < total; start += MAX_VALUE_LINE_LENGTH) { + int end = Math.min(total, start + MAX_VALUE_LINE_LENGTH); + String chunk = safe.substring(start, end); + MutableComponent labelComp = chunkIndex == 0 ? + label.copy() : + label.copy().append(Component.literal(" [" + (chunkIndex + 1) + "]")); + String chunkLabelText = labelComp.getString(); + // Each chunk copies the full "label: chunk" text, so the user can paste complete information. + lines.add(buildLine(labelComp, chunk, chunkLabelText + ": " + chunk)); + chunkIndex++; + } + // Trailing summary line (not copyable, just informative). + lines.add(Component.translatable("command.ctnhlib.value.truncated", total) + .withStyle(ChatFormatting.GRAY)); + return lines; + } + + /** + * Build a single chat line whose visible text is "label: value" and whose click event + * copies the supplied {@code copyText} verbatim. + */ + public static Component buildLine(Component label, String value, String copyText) { + MutableComponent labelStyled = label.copy().withStyle(ChatFormatting.AQUA); + MutableComponent valueStyled = Component.literal(value).withStyle(ChatFormatting.WHITE); + MutableComponent line = Component.empty() + .append(labelStyled) + .append(Component.literal(": ").withStyle(ChatFormatting.GRAY)) + .append(valueStyled); + + Style style = Style.EMPTY + .withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, copyText)) + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, + Component.translatable("command.ctnhlib.copy.hover"))); + return line.withStyle(style); + } + + /** Section heading line (no copy click event). */ + public static Component heading(Component component) { + return component.copy().withStyle(ChatFormatting.GOLD); + } + + /** A simple informational line such as "no fluid contained" with no copy event. */ + public static Component info(Component component) { + return component.copy().withStyle(ChatFormatting.GRAY); + } + + /** A red error line used by command failure paths. */ + public static Component error(Component component) { + return component.copy().withStyle(ChatFormatting.RED); + } + + /** + * Build a single click-to-copy chat line whose visible text is the supplied + * {@code visible} component (no automatic label prefix), and whose click event + * copies the supplied {@code copyText}. + */ + public static Component clickableLine(MutableComponent visible, String copyText) { + Style style = Style.EMPTY + .withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, copyText)) + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, + Component.translatable("command.ctnhlib.copy.hover"))); + return visible.withStyle(style); + } +} diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandInspector.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandInspector.java new file mode 100644 index 0000000..a580919 --- /dev/null +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandInspector.java @@ -0,0 +1,233 @@ +package tech.vixhentx.mcmod.ctnhlib.command; + +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.material.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidUtil; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; +import net.minecraftforge.registries.ForgeRegistries; + +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + * Read-only utility helpers for the /ctnh inspection commands. Centralizes + * resource-id/name/NBT/tag extraction for items, blocks, and fluids, and tag-member + * enumeration via {@link RegistryAccess} so datapack changes are honored at runtime. + */ +public final class CTNHCommandInspector { + + private CTNHCommandInspector() {} + + /** Lightweight payload describing a single fluid inside a held container. */ + public record FluidEntry(FluidStack stack) { + + public Fluid fluid() { + return stack.getFluid(); + } + + public Component displayName() { + return stack.getDisplayName(); + } + + public ResourceLocation id() { + ResourceLocation key = ForgeRegistries.FLUIDS.getKey(stack.getFluid()); + return key != null ? key : ResourceLocation.tryBuild("minecraft", "empty"); + } + + public int amount() { + return stack.getAmount(); + } + + @Nullable + public CompoundTag tag() { + return stack.getTag(); + } + + public List tags() { + List out = new ArrayList<>(); + stack.getFluid().builtInRegistryHolder().tags().forEach(t -> out.add(t.location())); + Collections.sort(out, (a, b) -> a.toString().compareTo(b.toString())); + return out; + } + } + + /** Item registry id, falling back to {@code minecraft:air} when missing. */ + public static ResourceLocation itemId(ItemStack stack) { + ResourceLocation id = ForgeRegistries.ITEMS.getKey(stack.getItem()); + return id != null ? id : ResourceLocation.tryBuild("minecraft", "air"); + } + + /** Block registry id for a {@link BlockItem}, or null when the stack is not a block item. */ + @Nullable + public static ResourceLocation blockId(ItemStack stack) { + if (stack.getItem() instanceof BlockItem blockItem) { + Block block = blockItem.getBlock(); + return ForgeRegistries.BLOCKS.getKey(block); + } + return null; + } + + /** Sorted item tag ids attached to the stack's item. */ + public static List itemTags(ItemStack stack) { + List out = new ArrayList<>(); + stack.getItem().builtInRegistryHolder().tags().forEach(t -> out.add(t.location())); + Collections.sort(out, (a, b) -> a.toString().compareTo(b.toString())); + return out; + } + + /** Sorted block tag ids attached to the block backing a {@link BlockItem}. */ + public static List blockTags(ItemStack stack) { + if (!(stack.getItem() instanceof BlockItem blockItem)) { + return Collections.emptyList(); + } + List out = new ArrayList<>(); + blockItem.getBlock().builtInRegistryHolder().tags().forEach(t -> out.add(t.location())); + Collections.sort(out, (a, b) -> a.toString().compareTo(b.toString())); + return out; + } + + /** + * Enumerate every non-empty fluid contained in the stack. Multi-tank containers + * walk their {@link IFluidHandlerItem} tank-by-tank; single-fluid items fall back + * to {@link FluidUtil#getFluidContained(ItemStack)} for compatibility. + */ + public static List fluidsIn(ItemStack stack) { + if (stack.isEmpty()) { + return Collections.emptyList(); + } + Optional handlerOpt = stack + .getCapability(net.minecraftforge.common.capabilities.ForgeCapabilities.FLUID_HANDLER_ITEM) + .resolve(); + List entries = new ArrayList<>(); + if (handlerOpt.isPresent()) { + IFluidHandler handler = handlerOpt.get(); + int tanks = handler.getTanks(); + for (int i = 0; i < tanks; i++) { + FluidStack fluid = handler.getFluidInTank(i); + if (fluid != null && !fluid.isEmpty()) { + entries.add(new FluidEntry(fluid.copy())); + } + } + if (!entries.isEmpty()) { + return entries; + } + } + FluidUtil.getFluidContained(stack) + .filter(f -> !f.isEmpty()) + .ifPresent(f -> entries.add(new FluidEntry(f.copy()))); + return entries; + } + + /** Resolve a string to {@code ResourceKey>} for the given inspection type. */ + public static ResourceKey> registryKeyFor(InspectType type) { + return switch (type) { + case ITEM -> Registries.ITEM; + case BLOCK -> Registries.BLOCK; + case FLUID -> Registries.FLUID; + }; + } + + /** + * Resolve a tag against the runtime registry exposed by the command source. Returns the + * holder set if the tag exists, otherwise {@link Optional#empty()}. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static Optional> resolveTag(CommandSourceStack source, + InspectType type, + ResourceLocation tagId) { + ResourceKey registryKey = registryKeyFor(type); + RegistryAccess access = source.registryAccess(); + Optional> registryOpt = access.registry(registryKey); + if (registryOpt.isEmpty()) { + return Optional.empty(); + } + Registry registry = registryOpt.get(); + TagKey tagKey = TagKey.create(registryKey, tagId); + return registry.getTag(tagKey).map(set -> (HolderSet.Named) set); + } + + /** Members of a tag in iteration order, mapped to (display name, registry id) pairs. */ + public static List listTagMembers(InspectType type, HolderSet.Named set) { + List result = new ArrayList<>(); + for (Holder holder : set) { + Object value = holder.value(); + ResourceLocation id = holder.unwrapKey().map(ResourceKey::location).orElse(null); + if (id == null) { + continue; + } + Component name = displayNameFor(type, value, id); + result.add(new TagMember(id, name)); + } + return result; + } + + private static Component displayNameFor(InspectType type, Object value, ResourceLocation id) { + return switch (type) { + case ITEM -> { + if (value instanceof net.minecraft.world.item.Item item) { + yield Component.translatable(item.getDescriptionId()); + } + yield Component.literal(id.toString()); + } + case BLOCK -> { + if (value instanceof Block block) { + yield Component.translatable(block.getDescriptionId()); + } + yield Component.literal(id.toString()); + } + case FLUID -> { + if (value instanceof Fluid fluid) { + yield new FluidStack(fluid, 1).getDisplayName(); + } + yield Component.literal(id.toString()); + } + }; + } + + /** Result entry for {@link #listTagMembers(InspectType, HolderSet.Named)}. */ + public record TagMember(ResourceLocation id, Component displayName) {} + + /** Pretty-print a CompoundTag for chat display (single-line SNBT form). */ + public static String prettyNbt(@Nullable CompoundTag tag) { + if (tag == null || tag.isEmpty()) { + return ""; + } + return tag.toString(); + } + + /** Inspection target type. */ + + public enum InspectType { + + ITEM, + BLOCK, + FLUID; + + public String registryDisplay() { + return switch (this) { + case ITEM -> "minecraft:item"; + case BLOCK -> "minecraft:block"; + case FLUID -> "minecraft:fluid"; + }; + } + } +} diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java new file mode 100644 index 0000000..2569d26 --- /dev/null +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java @@ -0,0 +1,234 @@ +package tech.vixhentx.mcmod.ctnhlib.command; + +import net.minecraft.ChatFormatting; +import net.minecraft.commands.CommandBuildContext; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.commands.arguments.ResourceLocationArgument; +import net.minecraft.core.HolderSet; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.suggestion.SuggestionProvider; +import tech.vixhentx.mcmod.ctnhlib.command.CTNHCommandInspector.FluidEntry; +import tech.vixhentx.mcmod.ctnhlib.command.CTNHCommandInspector.InspectType; +import tech.vixhentx.mcmod.ctnhlib.command.CTNHCommandInspector.TagMember; + +import java.util.List; +import java.util.Optional; + +import static net.minecraft.commands.Commands.argument; +import static net.minecraft.commands.Commands.literal; + +/** + * Brigadier registration entrypoint for the {@code /ctnh} inspection commands. + * Permission level is 0, so all players can run them. + */ +public final class CTNHCommands { + + /** Suggests known item/block/fluid tag IDs based on the requested inspection type. */ + private static final SuggestionProvider SUGGEST_TAGS = (ctx, builder) -> { + InspectType type = parseInspectType(ctx); + if (type == null) { + return builder.buildFuture(); + } + RegistryAccess access = ctx.getSource().registryAccess(); + ResourceKey> registryKey = CTNHCommandInspector.registryKeyFor(type); + Optional> registry = access.registry(registryKey); + registry.ifPresent(r -> SharedSuggestionProvider.suggestResource( + r.getTagNames().map(t -> t.location()), builder)); + return builder.buildFuture(); + }; + + private CTNHCommands() {} + + public static void register(CommandDispatcher dispatcher, + @SuppressWarnings("unused") CommandBuildContext buildContext) { + LiteralArgumentBuilder root = literal("ctnh") + .requires(src -> src.hasPermission(0)) + .then(literal("hand") + .executes(CTNHCommands::executeHand)) + .then(literal("showtag") + .then(literal("item") + .then(argument("tag", ResourceLocationArgument.id()) + .suggests(SUGGEST_TAGS) + .executes(ctx -> executeShowTag(ctx, InspectType.ITEM)))) + .then(literal("block") + .then(argument("tag", ResourceLocationArgument.id()) + .suggests(SUGGEST_TAGS) + .executes(ctx -> executeShowTag(ctx, InspectType.BLOCK)))) + .then(literal("fluid") + .then(argument("tag", ResourceLocationArgument.id()) + .suggests(SUGGEST_TAGS) + .executes(ctx -> executeShowTag(ctx, InspectType.FLUID))))); + dispatcher.register(root); + } + + private static InspectType parseInspectType(CommandContext ctx) { + String input = ctx.getInput(); + if (input.contains(" item ")) return InspectType.ITEM; + if (input.contains(" block ")) return InspectType.BLOCK; + if (input.contains(" fluid ")) return InspectType.FLUID; + return null; + } + + // ---- /ctnh hand ---------------------------------------------------------------- + + private static int executeHand(CommandContext ctx) { + CommandSourceStack source = ctx.getSource(); + ServerPlayer player = source.getPlayer(); + if (player == null) { + source.sendFailure(CTNHCommandChatHelper.error( + Component.translatable("command.ctnhlib.error.player_only"))); + return 0; + } + ItemStack stack = player.getItemInHand(InteractionHand.MAIN_HAND); + if (stack.isEmpty()) { + source.sendFailure(CTNHCommandChatHelper.error( + Component.translatable("command.ctnhlib.error.empty_hand"))); + return 0; + } + sendHandReport(player, stack); + return 1; + } + + private static void sendHandReport(ServerPlayer player, ItemStack stack) { + ResourceLocation itemId = CTNHCommandInspector.itemId(stack); + Component itemName = stack.getHoverName(); + // Item header. + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.item_name"), + itemName.getString()); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.item_id"), + itemId.toString()); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.item_count"), + String.valueOf(stack.getCount())); + + CompoundTag tag = stack.getTag(); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.item_nbt"), + CTNHCommandInspector.prettyNbt(tag)); + + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.item_tags"), + joinIds(CTNHCommandInspector.itemTags(stack))); + + // Block info, if applicable. + ResourceLocation blockId = CTNHCommandInspector.blockId(stack); + if (blockId != null) { + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.block_name"), + Component.translatable(stack.getItem().getDescriptionId()).getString()); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.block_id"), + blockId.toString()); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.block_tags"), + joinIds(CTNHCommandInspector.blockTags(stack))); + } + + // Fluid info, if applicable. + List fluids = CTNHCommandInspector.fluidsIn(stack); + if (fluids.isEmpty()) { + player.sendSystemMessage(CTNHCommandChatHelper.info( + Component.translatable("command.ctnhlib.hand.no_fluid"))); + return; + } + for (int i = 0; i < fluids.size(); i++) { + FluidEntry entry = fluids.get(i); + player.sendSystemMessage(CTNHCommandChatHelper.heading( + Component.translatable("command.ctnhlib.hand.fluid_header", i + 1))); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.fluid_name"), + entry.displayName().getString()); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.fluid_id"), + entry.id().toString()); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.fluid_amount"), + String.valueOf(entry.amount())); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.fluid_nbt"), + CTNHCommandInspector.prettyNbt(entry.tag())); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.fluid_tags"), + joinIds(entry.tags())); + } + } + + // ---- /ctnh showtag ------------------------------------------------------------- + + private static int executeShowTag(CommandContext ctx, InspectType type) { + CommandSourceStack source = ctx.getSource(); + ResourceLocation tagId = ResourceLocationArgument.getId(ctx, "tag"); + Optional> tagSet = CTNHCommandInspector.resolveTag(source, type, tagId); + if (tagSet.isEmpty()) { + source.sendFailure(CTNHCommandChatHelper.error( + Component.translatable("command.ctnhlib.error.unknown_tag", + tagId.toString(), type.registryDisplay()))); + return 0; + } + List members = CTNHCommandInspector.listTagMembers(type, tagSet.get()); + if (members.isEmpty()) { + source.sendFailure(CTNHCommandChatHelper.error( + Component.translatable("command.ctnhlib.error.empty_tag", + tagId.toString(), type.registryDisplay()))); + return 0; + } + Component header = Component.translatable("command.ctnhlib.showtag.header", + tagId.toString(), type.registryDisplay()).withStyle(ChatFormatting.GOLD); + source.sendSuccess(() -> header, false); + Component count = Component.translatable("command.ctnhlib.showtag.count", members.size()) + .withStyle(ChatFormatting.GRAY); + source.sendSuccess(() -> count, false); + for (TagMember member : members) { + String displayName = member.displayName().getString(); + String idString = member.id().toString(); + String copyText = String.format("- %s (%s)", displayName, idString); + String langKey = type == InspectType.FLUID ? + "command.ctnhlib.showtag.fluid_member" : + "command.ctnhlib.showtag.member"; + net.minecraft.network.chat.MutableComponent visible = Component + .translatable(langKey, displayName, idString) + .withStyle(ChatFormatting.WHITE); + Component line = CTNHCommandChatHelper.clickableLine(visible, copyText); + source.sendSuccess(() -> line, false); + } + return members.size(); + } + + // ---- helpers ------------------------------------------------------------------- + + private static String joinIds(List ids) { + if (ids == null || ids.isEmpty()) { + return ""; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ids.size(); i++) { + if (i > 0) sb.append(", "); + sb.append(ids.get(i).toString()); + } + return sb.toString(); + } + + private static void sendLabeled(ServerPlayer player, Component label, String value) { + String safeValue = value == null || value.isEmpty() ? + Component.translatable("command.ctnhlib.value.empty").getString() : + value; + for (Component line : CTNHCommandChatHelper.labeledLines(label, safeValue)) { + player.sendSystemMessage(line); + } + } +} diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/common/CommonProxy.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/common/CommonProxy.java index b470561..dc6e6e4 100644 --- a/src/main/java/tech/vixhentx/mcmod/ctnhlib/common/CommonProxy.java +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/common/CommonProxy.java @@ -4,12 +4,15 @@ import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.repository.Pack; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.AddPackFindersEvent; +import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import com.tterrag.registrate.util.entry.ItemEntry; +import tech.vixhentx.mcmod.ctnhlib.command.CTNHCommands; import tech.vixhentx.mcmod.ctnhlib.data.DataFilterPack; import tech.vixhentx.mcmod.ctnhlib.jade.GTProvidersRegistrar; import tech.vixhentx.mcmod.ctnhlib.registrate.CTNHLibNetworking; @@ -21,6 +24,8 @@ public class CommonProxy { public CommonProxy(FMLJavaModLoadingContext context) { IEventBus eventBus = context.getModEventBus(); eventBus.register(this); + // Forge-bus events such as RegisterCommandsEvent must be subscribed to the global Forge bus. + MinecraftForge.EVENT_BUS.register(CommonProxy.class); init(); ItemEntry multiblockHelper = REGISTRATE @@ -43,4 +48,9 @@ public void registerPackFinders(AddPackFindersEvent event) { DataFilterPack::new)); } } + + @SubscribeEvent + public static void registerCommands(RegisterCommandsEvent event) { + CTNHCommands.register(event.getDispatcher(), event.getBuildContext()); + } } diff --git a/src/main/resources/assets/ctnhlib/lang/en_us.json b/src/main/resources/assets/ctnhlib/lang/en_us.json new file mode 100644 index 0000000..705d09d --- /dev/null +++ b/src/main/resources/assets/ctnhlib/lang/en_us.json @@ -0,0 +1,29 @@ +{ + "command.ctnhlib.error.player_only": "This command can only be used by a player.", + "command.ctnhlib.error.empty_hand": "Your main hand is empty.", + "command.ctnhlib.error.unknown_tag": "Tag %1$s does not exist in registry %2$s.", + "command.ctnhlib.error.empty_tag": "Tag %1$s in registry %2$s has no members.", + "command.ctnhlib.copy.hover": "Click to copy", + "command.ctnhlib.value.empty": "", + "command.ctnhlib.value.none": "", + "command.ctnhlib.value.truncated": " (truncated, %1$s chars)", + "command.ctnhlib.hand.item_name": "Item Name", + "command.ctnhlib.hand.item_id": "Item ID", + "command.ctnhlib.hand.item_count": "Item Count", + "command.ctnhlib.hand.item_nbt": "Item NBT", + "command.ctnhlib.hand.item_tags": "Item Tags", + "command.ctnhlib.hand.block_name": "Block Name", + "command.ctnhlib.hand.block_id": "Block ID", + "command.ctnhlib.hand.block_tags": "Block Tags", + "command.ctnhlib.hand.fluid_header": "Fluid #%1$s", + "command.ctnhlib.hand.fluid_name": "Fluid Name", + "command.ctnhlib.hand.fluid_id": "Fluid ID", + "command.ctnhlib.hand.fluid_amount": "Fluid Amount (mB)", + "command.ctnhlib.hand.fluid_nbt": "Fluid NBT", + "command.ctnhlib.hand.fluid_tags": "Fluid Tags", + "command.ctnhlib.hand.no_fluid": "No fluid contained.", + "command.ctnhlib.showtag.header": "Tag %1$s in registry %2$s:", + "command.ctnhlib.showtag.count": "Members: %1$s", + "command.ctnhlib.showtag.member": "- %1$s (%2$s)", + "command.ctnhlib.showtag.fluid_member": "- %1$s (%2$s)" +} diff --git a/src/main/resources/assets/ctnhlib/lang/zh_cn.json b/src/main/resources/assets/ctnhlib/lang/zh_cn.json new file mode 100644 index 0000000..0854ecf --- /dev/null +++ b/src/main/resources/assets/ctnhlib/lang/zh_cn.json @@ -0,0 +1,29 @@ +{ + "command.ctnhlib.error.player_only": "该指令只能由玩家执行。", + "command.ctnhlib.error.empty_hand": "你的主手为空。", + "command.ctnhlib.error.unknown_tag": "标签 %1$s 在注册表 %2$s 中不存在。", + "command.ctnhlib.error.empty_tag": "注册表 %2$s 中的标签 %1$s 没有任何成员。", + "command.ctnhlib.copy.hover": "点击复制", + "command.ctnhlib.value.empty": "<空>", + "command.ctnhlib.value.none": "<无>", + "command.ctnhlib.value.truncated": "(已截断,共 %1$s 字符)", + "command.ctnhlib.hand.item_name": "物品名称", + "command.ctnhlib.hand.item_id": "物品ID", + "command.ctnhlib.hand.item_count": "物品数量", + "command.ctnhlib.hand.item_nbt": "物品NBT", + "command.ctnhlib.hand.item_tags": "物品标签", + "command.ctnhlib.hand.block_name": "方块名称", + "command.ctnhlib.hand.block_id": "方块ID", + "command.ctnhlib.hand.block_tags": "方块标签", + "command.ctnhlib.hand.fluid_header": "流体 #%1$s", + "command.ctnhlib.hand.fluid_name": "流体名称", + "command.ctnhlib.hand.fluid_id": "流体ID", + "command.ctnhlib.hand.fluid_amount": "流体数量(mB)", + "command.ctnhlib.hand.fluid_nbt": "流体NBT", + "command.ctnhlib.hand.fluid_tags": "流体标签", + "command.ctnhlib.hand.no_fluid": "无内含流体。", + "command.ctnhlib.showtag.header": "注册表 %2$s 中的标签 %1$s:", + "command.ctnhlib.showtag.count": "成员数:%1$s", + "command.ctnhlib.showtag.member": "- %1$s (%2$s)", + "command.ctnhlib.showtag.fluid_member": "- %1$s (%2$s)" +} From 82b3a728b5660faac1473da1406411d6f207ac06 Mon Sep 17 00:00:00 2001 From: m1Riss <3081974632@qq.com> Date: Thu, 28 May 2026 23:56:25 +0800 Subject: [PATCH 2/5] i18n(comments): translate command class comments to Chinese --- .../command/CTNHCommandChatHelper.java | 34 +++++++++--------- .../ctnhlib/command/CTNHCommandInspector.java | 36 +++++++++---------- .../mcmod/ctnhlib/command/CTNHCommands.java | 18 +++++----- 3 files changed, 43 insertions(+), 45 deletions(-) diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java index b16f0aa..4d2ea8b 100644 --- a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java @@ -11,23 +11,23 @@ import java.util.List; /** - * Helpers for building click-to-copy chat lines used by /ctnh inspection commands. - * Each emitted line copies the full "label: value" text on click and shows a hover tooltip. + * 用于构建 /ctnh 检查命令的点击复制聊天行的辅助工具。 + * 每行输出的文本在点击时会复制完整的 "label: value" 内容,并显示悬浮提示。 */ public final class CTNHCommandChatHelper { - /** Maximum length of a single chat line value before it is split into chunks. */ + /** 单个聊天行值的最大长度,超过该长度将拆分为多个块。 */ public static final int MAX_VALUE_LINE_LENGTH = 256; private CTNHCommandChatHelper() {} /** - * Build one or more clickable chat lines for a labeled value. Long values are split into - * additional copyable continuation lines so chat does not silently drop content. + * 为带标签的值构建一个或多个可点击的聊天行。长值将被拆分为 + * 额外的可复制续行,以避免聊天窗口静默丢弃内容。 * - * @param label localized label - * @param value raw value string (must not be null) - * @return one or more {@link Component} lines ready to be sent + * @param label 本地化标签 + * @param value 原始值字符串(不能为 null) + * @return 一个或多个可发送的 {@link Component} 行 */ public static List labeledLines(Component label, String value) { List lines = new ArrayList<>(); @@ -46,19 +46,18 @@ public static List labeledLines(Component label, String value) { label.copy() : label.copy().append(Component.literal(" [" + (chunkIndex + 1) + "]")); String chunkLabelText = labelComp.getString(); - // Each chunk copies the full "label: chunk" text, so the user can paste complete information. + // 每个块复制完整的 "label: chunk" 文本,以便用户粘贴完整信息。 lines.add(buildLine(labelComp, chunk, chunkLabelText + ": " + chunk)); chunkIndex++; } - // Trailing summary line (not copyable, just informative). + // 尾部摘要行(不可复制,仅用于提示信息)。 lines.add(Component.translatable("command.ctnhlib.value.truncated", total) .withStyle(ChatFormatting.GRAY)); return lines; } /** - * Build a single chat line whose visible text is "label: value" and whose click event - * copies the supplied {@code copyText} verbatim. + * 构建单个聊天行,其可见文本为 "label: value",单击事件将逐字复制提供的 {@code copyText}。 */ public static Component buildLine(Component label, String value, String copyText) { MutableComponent labelStyled = label.copy().withStyle(ChatFormatting.AQUA); @@ -75,25 +74,24 @@ public static Component buildLine(Component label, String value, String copyText return line.withStyle(style); } - /** Section heading line (no copy click event). */ + /** 分区标题行(无复制点击事件)。 */ public static Component heading(Component component) { return component.copy().withStyle(ChatFormatting.GOLD); } - /** A simple informational line such as "no fluid contained" with no copy event. */ + /** 简单的信息提示行,例如"未包含流体",无复制事件。 */ public static Component info(Component component) { return component.copy().withStyle(ChatFormatting.GRAY); } - /** A red error line used by command failure paths. */ + /** 命令失败时使用的红色错误行。 */ public static Component error(Component component) { return component.copy().withStyle(ChatFormatting.RED); } /** - * Build a single click-to-copy chat line whose visible text is the supplied - * {@code visible} component (no automatic label prefix), and whose click event - * copies the supplied {@code copyText}. + * 构建单个点击复制聊天行,其可见文本为提供的 + * {@code visible} 组件(无自动标签前缀),点击事件将复制提供的 {@code copyText}。 */ public static Component clickableLine(MutableComponent visible, String copyText) { Style style = Style.EMPTY diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandInspector.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandInspector.java index a580919..49c0572 100644 --- a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandInspector.java +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandInspector.java @@ -29,15 +29,15 @@ import java.util.Optional; /** - * Read-only utility helpers for the /ctnh inspection commands. Centralizes - * resource-id/name/NBT/tag extraction for items, blocks, and fluids, and tag-member - * enumeration via {@link RegistryAccess} so datapack changes are honored at runtime. + * 用于 /ctnh 检查命令的只读工具辅助类。集中处理物品、方块和流体的 + * 资源 ID/名称/NBT/标签提取,以及通过 {@link RegistryAccess} 进行标签成员 + * 枚举,从而在运行时尊重数据包变更。 */ public final class CTNHCommandInspector { private CTNHCommandInspector() {} - /** Lightweight payload describing a single fluid inside a held container. */ + /** 描述手持容器中单个流体的轻量级负载数据结构。 */ public record FluidEntry(FluidStack stack) { public Fluid fluid() { @@ -70,13 +70,13 @@ public List tags() { } } - /** Item registry id, falling back to {@code minecraft:air} when missing. */ + /** 物品注册 ID,缺失时回退为 {@code minecraft:air}。 */ public static ResourceLocation itemId(ItemStack stack) { ResourceLocation id = ForgeRegistries.ITEMS.getKey(stack.getItem()); return id != null ? id : ResourceLocation.tryBuild("minecraft", "air"); } - /** Block registry id for a {@link BlockItem}, or null when the stack is not a block item. */ + /** {@link BlockItem} 的方块注册 ID,如果该物品栈不是方块物品则返回 null。 */ @Nullable public static ResourceLocation blockId(ItemStack stack) { if (stack.getItem() instanceof BlockItem blockItem) { @@ -86,7 +86,7 @@ public static ResourceLocation blockId(ItemStack stack) { return null; } - /** Sorted item tag ids attached to the stack's item. */ + /** 附加到物品栈物品上的已排序物品标签 ID。 */ public static List itemTags(ItemStack stack) { List out = new ArrayList<>(); stack.getItem().builtInRegistryHolder().tags().forEach(t -> out.add(t.location())); @@ -94,7 +94,7 @@ public static List itemTags(ItemStack stack) { return out; } - /** Sorted block tag ids attached to the block backing a {@link BlockItem}. */ + /** 附加到 {@link BlockItem} 背后方块上的已排序方块标签 ID。 */ public static List blockTags(ItemStack stack) { if (!(stack.getItem() instanceof BlockItem blockItem)) { return Collections.emptyList(); @@ -106,9 +106,9 @@ public static List blockTags(ItemStack stack) { } /** - * Enumerate every non-empty fluid contained in the stack. Multi-tank containers - * walk their {@link IFluidHandlerItem} tank-by-tank; single-fluid items fall back - * to {@link FluidUtil#getFluidContained(ItemStack)} for compatibility. + * 枚举物品栈中包含的所有非空流体。多槽容器逐槽遍历其 + * {@link IFluidHandlerItem};单流体物品回退到 + * {@link FluidUtil#getFluidContained(ItemStack)} 以保证兼容性。 */ public static List fluidsIn(ItemStack stack) { if (stack.isEmpty()) { @@ -137,7 +137,7 @@ public static List fluidsIn(ItemStack stack) { return entries; } - /** Resolve a string to {@code ResourceKey>} for the given inspection type. */ + /** 将给定的检查类型解析为对应的 {@code ResourceKey>}。 */ public static ResourceKey> registryKeyFor(InspectType type) { return switch (type) { case ITEM -> Registries.ITEM; @@ -147,8 +147,8 @@ public static ResourceKey> registryKeyFor(InspectType type } /** - * Resolve a tag against the runtime registry exposed by the command source. Returns the - * holder set if the tag exists, otherwise {@link Optional#empty()}. + * 根据命令源暴露的运行时注册表解析标签。如果标签存在则返回 + * holder set,否则返回 {@link Optional#empty()}。 */ @SuppressWarnings({ "unchecked", "rawtypes" }) public static Optional> resolveTag(CommandSourceStack source, @@ -165,7 +165,7 @@ public static Optional> resolveTag(CommandSourceStack source, return registry.getTag(tagKey).map(set -> (HolderSet.Named) set); } - /** Members of a tag in iteration order, mapped to (display name, registry id) pairs. */ + /** 按迭代顺序返回标签成员,映射为(显示名称,注册 ID)对。 */ public static List listTagMembers(InspectType type, HolderSet.Named set) { List result = new ArrayList<>(); for (Holder holder : set) { @@ -203,10 +203,10 @@ private static Component displayNameFor(InspectType type, Object value, Resource }; } - /** Result entry for {@link #listTagMembers(InspectType, HolderSet.Named)}. */ + /** {@link #listTagMembers(InspectType, HolderSet.Named)} 的结果条目。 */ public record TagMember(ResourceLocation id, Component displayName) {} - /** Pretty-print a CompoundTag for chat display (single-line SNBT form). */ + /** 将 CompoundTag 格式化为适合聊天显示的字符串(单行 SNBT 形式)。 */ public static String prettyNbt(@Nullable CompoundTag tag) { if (tag == null || tag.isEmpty()) { return ""; @@ -214,7 +214,7 @@ public static String prettyNbt(@Nullable CompoundTag tag) { return tag.toString(); } - /** Inspection target type. */ + /** 检查目标类型。 */ public enum InspectType { diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java index 2569d26..7162df0 100644 --- a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java @@ -31,12 +31,12 @@ import static net.minecraft.commands.Commands.literal; /** - * Brigadier registration entrypoint for the {@code /ctnh} inspection commands. - * Permission level is 0, so all players can run them. + * Brigadier 注册入口,用于 {@code /ctnh} 检查命令。 + * 权限等级为 0,因此所有玩家均可执行。 */ public final class CTNHCommands { - /** Suggests known item/block/fluid tag IDs based on the requested inspection type. */ + /** 根据请求的检查类型,建议已知的物品/方块/流体标签 ID。 */ private static final SuggestionProvider SUGGEST_TAGS = (ctx, builder) -> { InspectType type = parseInspectType(ctx); if (type == null) { @@ -82,7 +82,7 @@ private static InspectType parseInspectType(CommandContext c return null; } - // ---- /ctnh hand ---------------------------------------------------------------- + // ---- /ctnh hand 手持物品检查 ---------------------------------------------------- private static int executeHand(CommandContext ctx) { CommandSourceStack source = ctx.getSource(); @@ -105,7 +105,7 @@ private static int executeHand(CommandContext ctx) { private static void sendHandReport(ServerPlayer player, ItemStack stack) { ResourceLocation itemId = CTNHCommandInspector.itemId(stack); Component itemName = stack.getHoverName(); - // Item header. + // 物品信息 sendLabeled(player, Component.translatable("command.ctnhlib.hand.item_name"), itemName.getString()); @@ -125,7 +125,7 @@ private static void sendHandReport(ServerPlayer player, ItemStack stack) { Component.translatable("command.ctnhlib.hand.item_tags"), joinIds(CTNHCommandInspector.itemTags(stack))); - // Block info, if applicable. + // 方块信息(如适用) ResourceLocation blockId = CTNHCommandInspector.blockId(stack); if (blockId != null) { sendLabeled(player, @@ -139,7 +139,7 @@ private static void sendHandReport(ServerPlayer player, ItemStack stack) { joinIds(CTNHCommandInspector.blockTags(stack))); } - // Fluid info, if applicable. + // 流体信息(如适用) List fluids = CTNHCommandInspector.fluidsIn(stack); if (fluids.isEmpty()) { player.sendSystemMessage(CTNHCommandChatHelper.info( @@ -168,7 +168,7 @@ private static void sendHandReport(ServerPlayer player, ItemStack stack) { } } - // ---- /ctnh showtag ------------------------------------------------------------- + // ---- /ctnh showtag 标签展示 ---------------------------------------------------- private static int executeShowTag(CommandContext ctx, InspectType type) { CommandSourceStack source = ctx.getSource(); @@ -209,7 +209,7 @@ private static int executeShowTag(CommandContext ctx, Inspec return members.size(); } - // ---- helpers ------------------------------------------------------------------- + // ---- 辅助方法 ------------------------------------------------------------------- private static String joinIds(List ids) { if (ids == null || ids.isEmpty()) { From 71d427172971f93c3aa69caace4473515d1eb041 Mon Sep 17 00:00:00 2001 From: m1Riss <3081974632@qq.com> Date: Fri, 29 May 2026 13:41:55 +0800 Subject: [PATCH 3/5] refactor(command): per-field colors, per-line tags, value-only copy --- .../command/CTNHCommandChatHelper.java | 48 ++++++++++-- .../mcmod/ctnhlib/command/CTNHCommands.java | 75 ++++++++++++------- 2 files changed, 87 insertions(+), 36 deletions(-) diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java index 4d2ea8b..9a16548 100644 --- a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java @@ -12,7 +12,7 @@ /** * 用于构建 /ctnh 检查命令的点击复制聊天行的辅助工具。 - * 每行输出的文本在点击时会复制完整的 "label: value" 内容,并显示悬浮提示。 + * 每行输出的文本在点击时会复制对应值内容,并显示悬浮提示。 */ public final class CTNHCommandChatHelper { @@ -30,11 +30,23 @@ private CTNHCommandChatHelper() {} * @return 一个或多个可发送的 {@link Component} 行 */ public static List labeledLines(Component label, String value) { + return labeledLines(label, value, ChatFormatting.WHITE); + } + + /** + * 为带标签的值构建一个或多个可点击的聊天行,并用指定颜色显示值部分。 + * 长值将被拆分为额外的可复制续行,以避免聊天窗口静默丢弃内容。 + * + * @param label 本地化标签 + * @param value 原始值字符串(不能为 null) + * @param valueColor 值文本颜色 + * @return 一个或多个可发送的 {@link Component} 行 + */ + public static List labeledLines(Component label, String value, ChatFormatting valueColor) { List lines = new ArrayList<>(); String safe = value == null ? "" : value; - String labelText = label.getString(); if (safe.length() <= MAX_VALUE_LINE_LENGTH) { - lines.add(buildLine(label, safe, labelText + ": " + safe)); + lines.add(buildLine(label, safe, safe, valueColor)); return lines; } int total = safe.length(); @@ -45,9 +57,8 @@ public static List labeledLines(Component label, String value) { MutableComponent labelComp = chunkIndex == 0 ? label.copy() : label.copy().append(Component.literal(" [" + (chunkIndex + 1) + "]")); - String chunkLabelText = labelComp.getString(); - // 每个块复制完整的 "label: chunk" 文本,以便用户粘贴完整信息。 - lines.add(buildLine(labelComp, chunk, chunkLabelText + ": " + chunk)); + // 每个块只复制对应值块,避免包含标签前缀。 + lines.add(buildLine(labelComp, chunk, chunk, valueColor)); chunkIndex++; } // 尾部摘要行(不可复制,仅用于提示信息)。 @@ -56,12 +67,35 @@ public static List labeledLines(Component label, String value) { return lines; } + /** 为多个标签 ID 构建逐行显示的可复制聊天行,每行点击时仅复制标签 ID。 */ + public static List labeledTagLines(Component label, List tagIds, ChatFormatting tagColor) { + List lines = new ArrayList<>(); + if (tagIds == null || tagIds.isEmpty()) { + lines.addAll(labeledLines(label, + Component.translatable("command.ctnhlib.value.empty").getString(), + tagColor)); + return lines; + } + for (String tagId : tagIds) { + String safe = tagId == null ? "" : tagId; + lines.add(buildLine(label, safe, safe, tagColor)); + } + return lines; + } + /** * 构建单个聊天行,其可见文本为 "label: value",单击事件将逐字复制提供的 {@code copyText}。 */ public static Component buildLine(Component label, String value, String copyText) { + return buildLine(label, value, copyText, ChatFormatting.WHITE); + } + + /** + * 构建单个聊天行,其可见文本为 "label: value",单击事件将逐字复制提供的 {@code copyText}。 + */ + public static Component buildLine(Component label, String value, String copyText, ChatFormatting valueColor) { MutableComponent labelStyled = label.copy().withStyle(ChatFormatting.AQUA); - MutableComponent valueStyled = Component.literal(value).withStyle(ChatFormatting.WHITE); + MutableComponent valueStyled = Component.literal(value).withStyle(valueColor); MutableComponent line = Component.empty() .append(labelStyled) .append(Component.literal(": ").withStyle(ChatFormatting.GRAY)) diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java index 7162df0..885af62 100644 --- a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java @@ -36,6 +36,12 @@ */ public final class CTNHCommands { + private static final ChatFormatting NAME_COLOR = ChatFormatting.AQUA; + private static final ChatFormatting RESOURCE_ID_COLOR = ChatFormatting.GREEN; + private static final ChatFormatting COUNT_COLOR = ChatFormatting.YELLOW; + private static final ChatFormatting NBT_COLOR = ChatFormatting.LIGHT_PURPLE; + private static final ChatFormatting TAG_COLOR = ChatFormatting.DARK_GREEN; + /** 根据请求的检查类型,建议已知的物品/方块/流体标签 ID。 */ private static final SuggestionProvider SUGGEST_TAGS = (ctx, builder) -> { InspectType type = parseInspectType(ctx); @@ -108,35 +114,41 @@ private static void sendHandReport(ServerPlayer player, ItemStack stack) { // 物品信息 sendLabeled(player, Component.translatable("command.ctnhlib.hand.item_name"), - itemName.getString()); + itemName.getString(), + NAME_COLOR); sendLabeled(player, Component.translatable("command.ctnhlib.hand.item_id"), - itemId.toString()); + itemId.toString(), + RESOURCE_ID_COLOR); sendLabeled(player, Component.translatable("command.ctnhlib.hand.item_count"), - String.valueOf(stack.getCount())); + String.valueOf(stack.getCount()), + COUNT_COLOR); CompoundTag tag = stack.getTag(); sendLabeled(player, Component.translatable("command.ctnhlib.hand.item_nbt"), - CTNHCommandInspector.prettyNbt(tag)); + CTNHCommandInspector.prettyNbt(tag), + NBT_COLOR); - sendLabeled(player, + sendTagLines(player, Component.translatable("command.ctnhlib.hand.item_tags"), - joinIds(CTNHCommandInspector.itemTags(stack))); + CTNHCommandInspector.itemTags(stack)); // 方块信息(如适用) ResourceLocation blockId = CTNHCommandInspector.blockId(stack); if (blockId != null) { sendLabeled(player, Component.translatable("command.ctnhlib.hand.block_name"), - Component.translatable(stack.getItem().getDescriptionId()).getString()); + Component.translatable(stack.getItem().getDescriptionId()).getString(), + NAME_COLOR); sendLabeled(player, Component.translatable("command.ctnhlib.hand.block_id"), - blockId.toString()); - sendLabeled(player, + blockId.toString(), + RESOURCE_ID_COLOR); + sendTagLines(player, Component.translatable("command.ctnhlib.hand.block_tags"), - joinIds(CTNHCommandInspector.blockTags(stack))); + CTNHCommandInspector.blockTags(stack)); } // 流体信息(如适用) @@ -152,19 +164,23 @@ private static void sendHandReport(ServerPlayer player, ItemStack stack) { Component.translatable("command.ctnhlib.hand.fluid_header", i + 1))); sendLabeled(player, Component.translatable("command.ctnhlib.hand.fluid_name"), - entry.displayName().getString()); + entry.displayName().getString(), + NAME_COLOR); sendLabeled(player, Component.translatable("command.ctnhlib.hand.fluid_id"), - entry.id().toString()); + entry.id().toString(), + RESOURCE_ID_COLOR); sendLabeled(player, Component.translatable("command.ctnhlib.hand.fluid_amount"), - String.valueOf(entry.amount())); + String.valueOf(entry.amount()), + COUNT_COLOR); sendLabeled(player, Component.translatable("command.ctnhlib.hand.fluid_nbt"), - CTNHCommandInspector.prettyNbt(entry.tag())); - sendLabeled(player, + CTNHCommandInspector.prettyNbt(entry.tag()), + NBT_COLOR); + sendTagLines(player, Component.translatable("command.ctnhlib.hand.fluid_tags"), - joinIds(entry.tags())); + entry.tags()); } } @@ -196,7 +212,7 @@ private static int executeShowTag(CommandContext ctx, Inspec for (TagMember member : members) { String displayName = member.displayName().getString(); String idString = member.id().toString(); - String copyText = String.format("- %s (%s)", displayName, idString); + String copyText = idString; String langKey = type == InspectType.FLUID ? "command.ctnhlib.showtag.fluid_member" : "command.ctnhlib.showtag.member"; @@ -211,23 +227,24 @@ private static int executeShowTag(CommandContext ctx, Inspec // ---- 辅助方法 ------------------------------------------------------------------- - private static String joinIds(List ids) { - if (ids == null || ids.isEmpty()) { - return ""; - } - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < ids.size(); i++) { - if (i > 0) sb.append(", "); - sb.append(ids.get(i).toString()); - } - return sb.toString(); + private static void sendLabeled(ServerPlayer player, Component label, String value) { + sendLabeled(player, label, value, ChatFormatting.WHITE); } - private static void sendLabeled(ServerPlayer player, Component label, String value) { + private static void sendLabeled(ServerPlayer player, Component label, String value, ChatFormatting valueColor) { String safeValue = value == null || value.isEmpty() ? Component.translatable("command.ctnhlib.value.empty").getString() : value; - for (Component line : CTNHCommandChatHelper.labeledLines(label, safeValue)) { + for (Component line : CTNHCommandChatHelper.labeledLines(label, safeValue, valueColor)) { + player.sendSystemMessage(line); + } + } + + private static void sendTagLines(ServerPlayer player, Component label, List tagIds) { + List tagIdStrings = tagIds == null ? + List.of() : + tagIds.stream().map(ResourceLocation::toString).toList(); + for (Component line : CTNHCommandChatHelper.labeledTagLines(label, tagIdStrings, TAG_COLOR)) { player.sendSystemMessage(line); } } From 7596a7502ac9a689f31cfe2aea5a27b68db846c0 Mon Sep 17 00:00:00 2001 From: m1Riss <3081974632@qq.com> Date: Fri, 29 May 2026 14:13:43 +0800 Subject: [PATCH 4/5] refactor(command): improve ctnh inspection output details --- .../command/CTNHCommandChatHelper.java | 82 ++++++++++++++++--- .../mcmod/ctnhlib/command/CTNHCommands.java | 70 ++++++++++++++-- .../resources/assets/ctnhlib/lang/en_us.json | 6 ++ .../resources/assets/ctnhlib/lang/zh_cn.json | 6 ++ 4 files changed, 146 insertions(+), 18 deletions(-) diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java index 9a16548..0d54c4a 100644 --- a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommandChatHelper.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.function.Function; /** * 用于构建 /ctnh 检查命令的点击复制聊天行的辅助工具。 @@ -43,10 +44,19 @@ public static List labeledLines(Component label, String value) { * @return 一个或多个可发送的 {@link Component} 行 */ public static List labeledLines(Component label, String value, ChatFormatting valueColor) { + return labeledLines(label, value, value, valueColor); + } + + /** + * 为带标签的值构建一个或多个可点击的聊天行,并允许显示值和复制值不同。 + */ + public static List labeledLines(Component label, String value, String copyText, + ChatFormatting valueColor) { List lines = new ArrayList<>(); String safe = value == null ? "" : value; + String safeCopy = copyText == null ? safe : copyText; if (safe.length() <= MAX_VALUE_LINE_LENGTH) { - lines.add(buildLine(label, safe, safe, valueColor)); + lines.add(buildLine(label, safe, safeCopy, valueColor)); return lines; } int total = safe.length(); @@ -54,11 +64,12 @@ public static List labeledLines(Component label, String value, ChatFo for (int start = 0; start < total; start += MAX_VALUE_LINE_LENGTH) { int end = Math.min(total, start + MAX_VALUE_LINE_LENGTH); String chunk = safe.substring(start, end); - MutableComponent labelComp = chunkIndex == 0 ? - label.copy() : - label.copy().append(Component.literal(" [" + (chunkIndex + 1) + "]")); - // 每个块只复制对应值块,避免包含标签前缀。 - lines.add(buildLine(labelComp, chunk, chunk, valueColor)); + if (chunkIndex == 0) { + lines.add(buildLine(label.copy(), chunk, chunk, valueColor)); + } else { + lines.add(buildContinuationLine(label, chunk, chunk, valueColor, + Component.translatable("command.ctnhlib.copy.hover"))); + } chunkIndex++; } // 尾部摘要行(不可复制,仅用于提示信息)。 @@ -69,6 +80,15 @@ public static List labeledLines(Component label, String value, ChatFo /** 为多个标签 ID 构建逐行显示的可复制聊天行,每行点击时仅复制标签 ID。 */ public static List labeledTagLines(Component label, List tagIds, ChatFormatting tagColor) { + return labeledTagLines(label, tagIds, tagColor, + ignored -> Component.translatable("command.ctnhlib.copy.hover")); + } + + /** 为多个标签 ID 构建逐行显示的可复制聊天行,并允许每行使用自定义悬浮提示。 */ + public static List labeledTagLines(Component label, + List tagIds, + ChatFormatting tagColor, + Function hoverFactory) { List lines = new ArrayList<>(); if (tagIds == null || tagIds.isEmpty()) { lines.addAll(labeledLines(label, @@ -76,9 +96,16 @@ public static List labeledTagLines(Component label, List tagI tagColor)); return lines; } - for (String tagId : tagIds) { + for (int i = 0; i < tagIds.size(); i++) { + String tagId = tagIds.get(i); String safe = tagId == null ? "" : tagId; - lines.add(buildLine(label, safe, safe, tagColor)); + Component hover = hoverFactory == null ? Component.translatable("command.ctnhlib.copy.hover") : + hoverFactory.apply(safe); + if (i == 0) { + lines.add(buildLine(label.copy(), safe, safe, tagColor, hover)); + } else { + lines.add(buildContinuationLine(label, safe, safe, tagColor, hover)); + } } return lines; } @@ -94,6 +121,17 @@ public static Component buildLine(Component label, String value, String copyText * 构建单个聊天行,其可见文本为 "label: value",单击事件将逐字复制提供的 {@code copyText}。 */ public static Component buildLine(Component label, String value, String copyText, ChatFormatting valueColor) { + return buildLine(label, value, copyText, valueColor, Component.translatable("command.ctnhlib.copy.hover")); + } + + /** + * 构建单个聊天行,其可见文本为 "label: value",并使用自定义悬浮提示。 + */ + public static Component buildLine(Component label, + String value, + String copyText, + ChatFormatting valueColor, + Component hoverText) { MutableComponent labelStyled = label.copy().withStyle(ChatFormatting.AQUA); MutableComponent valueStyled = Component.literal(value).withStyle(valueColor); MutableComponent line = Component.empty() @@ -103,8 +141,24 @@ public static Component buildLine(Component label, String value, String copyText Style style = Style.EMPTY .withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, copyText)) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, - Component.translatable("command.ctnhlib.copy.hover"))); + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverText)); + return line.withStyle(style); + } + + /** + * 构建续行(无标签和冒号),仅显示与首行值列对齐的值部分。 + * 使用空格填充来匹配首行 "label: " 的宽度,然后仅追加带颜色的值。 + */ + private static Component buildContinuationLine(Component label, String value, String copyText, + ChatFormatting valueColor, Component hoverText) { + int pad = label.getString().length() + 2; // "label: " + MutableComponent spacer = Component.literal(" ".repeat(Math.max(0, pad))); + MutableComponent valueStyled = Component.literal(value).withStyle(valueColor); + MutableComponent line = Component.empty().append(spacer).append(valueStyled); + + Style style = Style.EMPTY + .withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, copyText)) + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverText)); return line.withStyle(style); } @@ -128,10 +182,14 @@ public static Component error(Component component) { * {@code visible} 组件(无自动标签前缀),点击事件将复制提供的 {@code copyText}。 */ public static Component clickableLine(MutableComponent visible, String copyText) { + return clickableLine(visible, copyText, Component.translatable("command.ctnhlib.copy.hover")); + } + + /** 使用自定义悬浮提示构建无标签点击复制聊天行。 */ + public static Component clickableLine(MutableComponent visible, String copyText, Component hoverText) { Style style = Style.EMPTY .withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, copyText)) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, - Component.translatable("command.ctnhlib.copy.hover"))); + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverText)); return visible.withStyle(style); } } diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java index 885af62..7a2c629 100644 --- a/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/command/CTNHCommands.java @@ -41,6 +41,7 @@ public final class CTNHCommands { private static final ChatFormatting COUNT_COLOR = ChatFormatting.YELLOW; private static final ChatFormatting NBT_COLOR = ChatFormatting.LIGHT_PURPLE; private static final ChatFormatting TAG_COLOR = ChatFormatting.DARK_GREEN; + private static final ChatFormatting MOD_COLOR = ChatFormatting.DARK_AQUA; /** 根据请求的检查类型,建议已知的物品/方块/流体标签 ID。 */ private static final SuggestionProvider SUGGEST_TAGS = (ctx, builder) -> { @@ -120,6 +121,11 @@ private static void sendHandReport(ServerPlayer player, ItemStack stack) { Component.translatable("command.ctnhlib.hand.item_id"), itemId.toString(), RESOURCE_ID_COLOR); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.item_mod"), + modDisplay(itemId), + itemId.getNamespace(), + MOD_COLOR); sendLabeled(player, Component.translatable("command.ctnhlib.hand.item_count"), String.valueOf(stack.getCount()), @@ -131,9 +137,12 @@ private static void sendHandReport(ServerPlayer player, ItemStack stack) { CTNHCommandInspector.prettyNbt(tag), NBT_COLOR); + CommandSourceStack source = player.createCommandSourceStack(); sendTagLines(player, + source, Component.translatable("command.ctnhlib.hand.item_tags"), - CTNHCommandInspector.itemTags(stack)); + CTNHCommandInspector.itemTags(stack), + InspectType.ITEM); // 方块信息(如适用) ResourceLocation blockId = CTNHCommandInspector.blockId(stack); @@ -146,9 +155,16 @@ private static void sendHandReport(ServerPlayer player, ItemStack stack) { Component.translatable("command.ctnhlib.hand.block_id"), blockId.toString(), RESOURCE_ID_COLOR); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.block_mod"), + modDisplay(blockId), + blockId.getNamespace(), + MOD_COLOR); sendTagLines(player, + source, Component.translatable("command.ctnhlib.hand.block_tags"), - CTNHCommandInspector.blockTags(stack)); + CTNHCommandInspector.blockTags(stack), + InspectType.BLOCK); } // 流体信息(如适用) @@ -170,6 +186,11 @@ private static void sendHandReport(ServerPlayer player, ItemStack stack) { Component.translatable("command.ctnhlib.hand.fluid_id"), entry.id().toString(), RESOURCE_ID_COLOR); + sendLabeled(player, + Component.translatable("command.ctnhlib.hand.fluid_mod"), + modDisplay(entry.id()), + entry.id().getNamespace(), + MOD_COLOR); sendLabeled(player, Component.translatable("command.ctnhlib.hand.fluid_amount"), String.valueOf(entry.amount()), @@ -179,8 +200,10 @@ private static void sendHandReport(ServerPlayer player, ItemStack stack) { CTNHCommandInspector.prettyNbt(entry.tag()), NBT_COLOR); sendTagLines(player, + source, Component.translatable("command.ctnhlib.hand.fluid_tags"), - entry.tags()); + entry.tags(), + InspectType.FLUID); } } @@ -232,20 +255,55 @@ private static void sendLabeled(ServerPlayer player, Component label, String val } private static void sendLabeled(ServerPlayer player, Component label, String value, ChatFormatting valueColor) { + sendLabeled(player, label, value, value, valueColor); + } + + private static void sendLabeled(ServerPlayer player, + Component label, + String value, + String copyText, + ChatFormatting valueColor) { String safeValue = value == null || value.isEmpty() ? Component.translatable("command.ctnhlib.value.empty").getString() : value; - for (Component line : CTNHCommandChatHelper.labeledLines(label, safeValue, valueColor)) { + for (Component line : CTNHCommandChatHelper.labeledLines(label, safeValue, copyText, valueColor)) { player.sendSystemMessage(line); } } - private static void sendTagLines(ServerPlayer player, Component label, List tagIds) { + private static void sendTagLines(ServerPlayer player, + CommandSourceStack source, + Component label, + List tagIds, + InspectType type) { List tagIdStrings = tagIds == null ? List.of() : tagIds.stream().map(ResourceLocation::toString).toList(); - for (Component line : CTNHCommandChatHelper.labeledTagLines(label, tagIdStrings, TAG_COLOR)) { + for (Component line : CTNHCommandChatHelper.labeledTagLines(label, tagIdStrings, TAG_COLOR, + tagId -> tagHover(type, tagMemberCount(source, type, ResourceLocation.tryParse(tagId))))) { player.sendSystemMessage(line); } } + + private static String modDisplay(ResourceLocation id) { + return "@" + id.getNamespace(); + } + + private static int tagMemberCount(CommandSourceStack source, InspectType type, ResourceLocation tagId) { + if (tagId == null) { + return 0; + } + return CTNHCommandInspector.resolveTag(source, type, tagId) + .map(set -> CTNHCommandInspector.listTagMembers(type, set).size()) + .orElse(0); + } + + private static Component tagHover(InspectType type, int count) { + String key = switch (type) { + case ITEM -> "command.ctnhlib.copy.hover.item_tag"; + case BLOCK -> "command.ctnhlib.copy.hover.block_tag"; + case FLUID -> "command.ctnhlib.copy.hover.fluid_tag"; + }; + return Component.translatable(key, count); + } } diff --git a/src/main/resources/assets/ctnhlib/lang/en_us.json b/src/main/resources/assets/ctnhlib/lang/en_us.json index 705d09d..ca2d3f8 100644 --- a/src/main/resources/assets/ctnhlib/lang/en_us.json +++ b/src/main/resources/assets/ctnhlib/lang/en_us.json @@ -4,20 +4,26 @@ "command.ctnhlib.error.unknown_tag": "Tag %1$s does not exist in registry %2$s.", "command.ctnhlib.error.empty_tag": "Tag %1$s in registry %2$s has no members.", "command.ctnhlib.copy.hover": "Click to copy", + "command.ctnhlib.copy.hover.item_tag": "[%1$s items] Click to copy", + "command.ctnhlib.copy.hover.block_tag": "[%1$s blocks] Click to copy", + "command.ctnhlib.copy.hover.fluid_tag": "[%1$s fluids] Click to copy", "command.ctnhlib.value.empty": "", "command.ctnhlib.value.none": "", "command.ctnhlib.value.truncated": " (truncated, %1$s chars)", "command.ctnhlib.hand.item_name": "Item Name", "command.ctnhlib.hand.item_id": "Item ID", + "command.ctnhlib.hand.item_mod": "Item Mod", "command.ctnhlib.hand.item_count": "Item Count", "command.ctnhlib.hand.item_nbt": "Item NBT", "command.ctnhlib.hand.item_tags": "Item Tags", "command.ctnhlib.hand.block_name": "Block Name", "command.ctnhlib.hand.block_id": "Block ID", + "command.ctnhlib.hand.block_mod": "Block Mod", "command.ctnhlib.hand.block_tags": "Block Tags", "command.ctnhlib.hand.fluid_header": "Fluid #%1$s", "command.ctnhlib.hand.fluid_name": "Fluid Name", "command.ctnhlib.hand.fluid_id": "Fluid ID", + "command.ctnhlib.hand.fluid_mod": "Fluid Mod", "command.ctnhlib.hand.fluid_amount": "Fluid Amount (mB)", "command.ctnhlib.hand.fluid_nbt": "Fluid NBT", "command.ctnhlib.hand.fluid_tags": "Fluid Tags", diff --git a/src/main/resources/assets/ctnhlib/lang/zh_cn.json b/src/main/resources/assets/ctnhlib/lang/zh_cn.json index 0854ecf..3007741 100644 --- a/src/main/resources/assets/ctnhlib/lang/zh_cn.json +++ b/src/main/resources/assets/ctnhlib/lang/zh_cn.json @@ -4,20 +4,26 @@ "command.ctnhlib.error.unknown_tag": "标签 %1$s 在注册表 %2$s 中不存在。", "command.ctnhlib.error.empty_tag": "注册表 %2$s 中的标签 %1$s 没有任何成员。", "command.ctnhlib.copy.hover": "点击复制", + "command.ctnhlib.copy.hover.item_tag": "[%1$s个物品] 点击复制", + "command.ctnhlib.copy.hover.block_tag": "[%1$s个方块] 点击复制", + "command.ctnhlib.copy.hover.fluid_tag": "[%1$s个流体] 点击复制", "command.ctnhlib.value.empty": "<空>", "command.ctnhlib.value.none": "<无>", "command.ctnhlib.value.truncated": "(已截断,共 %1$s 字符)", "command.ctnhlib.hand.item_name": "物品名称", "command.ctnhlib.hand.item_id": "物品ID", + "command.ctnhlib.hand.item_mod": "物品Mod", "command.ctnhlib.hand.item_count": "物品数量", "command.ctnhlib.hand.item_nbt": "物品NBT", "command.ctnhlib.hand.item_tags": "物品标签", "command.ctnhlib.hand.block_name": "方块名称", "command.ctnhlib.hand.block_id": "方块ID", + "command.ctnhlib.hand.block_mod": "方块Mod", "command.ctnhlib.hand.block_tags": "方块标签", "command.ctnhlib.hand.fluid_header": "流体 #%1$s", "command.ctnhlib.hand.fluid_name": "流体名称", "command.ctnhlib.hand.fluid_id": "流体ID", + "command.ctnhlib.hand.fluid_mod": "流体Mod", "command.ctnhlib.hand.fluid_amount": "流体数量(mB)", "command.ctnhlib.hand.fluid_nbt": "流体NBT", "command.ctnhlib.hand.fluid_tags": "流体标签", From 18c4bdfe514d0eeb419dbb31a6e9ac7143c9e9c2 Mon Sep 17 00:00:00 2001 From: m1Riss <3081974632@qq.com> Date: Fri, 29 May 2026 14:26:31 +0800 Subject: [PATCH 5/5] fix:spotless --- .gitignore | 4 ++++ src/main/java/com/ctnhlang/IgnoreLang.java | 3 +-- .../com/ctnhlang/langprovider/LangKeyBuilder.java | 10 +++++----- .../vixhentx/mcmod/ctnhlib/langprovider/Lang.java | 2 +- .../mcmod/ctnhlib/langprovider/LangProcessor.java | 14 ++++++++------ 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index d5f737e..eff8b2d 100644 --- a/.gitignore +++ b/.gitignore @@ -117,3 +117,7 @@ runs/ # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) !gradle-wrapper.jar + +#OMO +.omo + diff --git a/src/main/java/com/ctnhlang/IgnoreLang.java b/src/main/java/com/ctnhlang/IgnoreLang.java index de8141e..42ac057 100644 --- a/src/main/java/com/ctnhlang/IgnoreLang.java +++ b/src/main/java/com/ctnhlang/IgnoreLang.java @@ -7,5 +7,4 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) -public @interface IgnoreLang { -} +public @interface IgnoreLang {} diff --git a/src/main/java/com/ctnhlang/langprovider/LangKeyBuilder.java b/src/main/java/com/ctnhlang/langprovider/LangKeyBuilder.java index ba7ee1b..91b670b 100644 --- a/src/main/java/com/ctnhlang/langprovider/LangKeyBuilder.java +++ b/src/main/java/com/ctnhlang/langprovider/LangKeyBuilder.java @@ -93,7 +93,8 @@ private static ClassMetadata fromClass(Class ownerClass) { return new ClassMetadata( domain != null ? domain.value() : "", "", - resolveCategory(domain != null ? domain.value() : "", category != null ? category.value() : "", ownerClass.getSimpleName()), + resolveCategory(domain != null ? domain.value() : "", category != null ? category.value() : "", + ownerClass.getSimpleName()), prefix != null ? resolveAffix(prefix.value(), ownerClass.getSimpleName()) : "", suffix != null ? resolveAffix(suffix.value(), ownerClass.getSimpleName()) : ""); } @@ -119,7 +120,8 @@ private static ClassMetadata fromClassNode(ClassNode classNode) { } } - return new ClassMetadata(domain, root, resolveCategory(domain, category, simpleName(classNode.name)), prefix, suffix); + return new ClassMetadata(domain, root, resolveCategory(domain, category, simpleName(classNode.name)), prefix, + suffix); } private static String getExplicitKey(Field field) { @@ -158,9 +160,7 @@ private static String resolveCategory(String domain, String explicitCategory, St } private static String resolveAffix(String explicitValue, String className) { - return explicitValue == null || explicitValue.isEmpty() - ? className.toLowerCase(Locale.ROOT) - : explicitValue; + return explicitValue == null || explicitValue.isEmpty() ? className.toLowerCase(Locale.ROOT) : explicitValue; } private static String simpleName(String internalName) { diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/langprovider/Lang.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/langprovider/Lang.java index fd478d6..583bf4f 100644 --- a/src/main/java/tech/vixhentx/mcmod/ctnhlib/langprovider/Lang.java +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/langprovider/Lang.java @@ -1,9 +1,9 @@ package tech.vixhentx.mcmod.ctnhlib.langprovider; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import com.ctnhlang.LangFactory; -import net.minecraft.network.chat.MutableComponent; @LangFactory public final class Lang implements com.ctnhlang.Lang { diff --git a/src/main/java/tech/vixhentx/mcmod/ctnhlib/langprovider/LangProcessor.java b/src/main/java/tech/vixhentx/mcmod/ctnhlib/langprovider/LangProcessor.java index 7f72072..ff40328 100644 --- a/src/main/java/tech/vixhentx/mcmod/ctnhlib/langprovider/LangProcessor.java +++ b/src/main/java/tech/vixhentx/mcmod/ctnhlib/langprovider/LangProcessor.java @@ -1,8 +1,5 @@ package tech.vixhentx.mcmod.ctnhlib.langprovider; -import com.ctnhlang.CN; -import com.ctnhlang.EN; -import com.ctnhlang.IgnoreLang; import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.ModList; import net.minecraftforge.forgespi.language.IModFileInfo; @@ -10,6 +7,9 @@ import net.minecraftforge.forgespi.language.ModFileScanData; import net.minecraftforge.forgespi.locating.IModFile; +import com.ctnhlang.CN; +import com.ctnhlang.EN; +import com.ctnhlang.IgnoreLang; import com.ctnhlang.langprovider.LangKeyBuilder; import org.objectweb.asm.ClassReader; import org.objectweb.asm.Type; @@ -18,9 +18,9 @@ import tech.vixhentx.mcmod.ctnhlib.CTNHLib; import tech.vixhentx.mcmod.ctnhlib.registrate.CNRegistrate; -import java.lang.annotation.ElementType; import java.io.IOException; import java.io.InputStream; +import java.lang.annotation.ElementType; import java.util.HashMap; import java.util.Map; @@ -119,7 +119,8 @@ private void processField(ModFileScanData.AnnotationData enData, } } if (enValues.length != cnValues.length && enValues.length != 0 && cnValues.length != 0) { - CTNHLib.LOGGER.warn("Mismatched @EN/@CN array lengths on {}#{}", primary.clazz().getClassName(), field.name); + CTNHLib.LOGGER.warn("Mismatched @EN/@CN array lengths on {}#{}", primary.clazz().getClassName(), + field.name); } return; } @@ -139,7 +140,8 @@ private ClassNode readClassNode(String className) throws IOException { return null; } ClassNode classNode = new ClassNode(); - new ClassReader(stream).accept(classNode, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + new ClassReader(stream).accept(classNode, + ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); return classNode; } }