From fcc7cf46598f025b498a81c033919e0e4e502f1b Mon Sep 17 00:00:00 2001 From: BRanulf_Explode Date: Sun, 24 Aug 2025 18:56:19 +0800 Subject: [PATCH] huh --- gradle.properties | 2 +- .../java/org/branulf/toolbox/ModConfig.java | 11 + .../damagelogger/DamageLoggerHandler.java | 1 + .../mixin/showenchants/DrawContextMixin.java | 206 ++++++++++++++++++ .../assets/branulf_toolbox/lang/en_us.json | 7 +- .../assets/branulf_toolbox/lang/zh_cn.json | 13 +- .../resources/branulf_toolbox.mixins.json | 13 ++ src/main/resources/fabric.mod.json | 3 + 8 files changed, 250 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/branulf/toolbox/mixin/showenchants/DrawContextMixin.java create mode 100644 src/main/resources/branulf_toolbox.mixins.json diff --git a/gradle.properties b/gradle.properties index 780fde6..6fe62d0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ minecraft_version=1.21.4 yarn_mappings=1.21.4+build.8 loader_version=0.16.10 # Mod Properties -mod_version=1.14.514.005 +mod_version=1.14.514.006 maven_group=org.branulf archives_base_name=branulf_toolbox # Dependencies diff --git a/src/main/java/org/branulf/toolbox/ModConfig.java b/src/main/java/org/branulf/toolbox/ModConfig.java index 4c446ad..f83ffa4 100644 --- a/src/main/java/org/branulf/toolbox/ModConfig.java +++ b/src/main/java/org/branulf/toolbox/ModConfig.java @@ -40,6 +40,11 @@ public class ModConfig implements ConfigData { @ConfigEntry.Gui.TransitiveObject public DamageLoggerConfig damageLogger = new DamageLoggerConfig(); + // 显示附魔 + @ConfigEntry.Category("show_enchants_settings") + @ConfigEntry.Gui.TransitiveObject + public ShowEnchantsConfig showEnchants = new ShowEnchantsConfig(); + // ————————————————————分割线———————————————————— @@ -120,4 +125,10 @@ public class ModConfig implements ConfigData { @ConfigEntry.Gui.Tooltip(count = 1) public boolean rememberState = false; } + + // 显示附魔 + public static class ShowEnchantsConfig implements ConfigData { + @ConfigEntry.Gui.Tooltip(count = 2) + public boolean enabled = true; + } } diff --git a/src/main/java/org/branulf/toolbox/damagelogger/DamageLoggerHandler.java b/src/main/java/org/branulf/toolbox/damagelogger/DamageLoggerHandler.java index b3aba7f..2eeea69 100644 --- a/src/main/java/org/branulf/toolbox/damagelogger/DamageLoggerHandler.java +++ b/src/main/java/org/branulf/toolbox/damagelogger/DamageLoggerHandler.java @@ -317,6 +317,7 @@ public class DamageLoggerHandler { return source.getName(); } + // 这里用了AI,翻译不准确,明天再改,我知道有问题。 private String getDamageType(DamageSource source) { if (source.isOf(DamageTypes.OUT_OF_WORLD)) return "虚空伤害"; if (source.isOf(DamageTypes.BAD_RESPAWN_POINT)) return "错误重生点爆炸伤害"; diff --git a/src/main/java/org/branulf/toolbox/mixin/showenchants/DrawContextMixin.java b/src/main/java/org/branulf/toolbox/mixin/showenchants/DrawContextMixin.java new file mode 100644 index 0000000..95d40a3 --- /dev/null +++ b/src/main/java/org/branulf/toolbox/mixin/showenchants/DrawContextMixin.java @@ -0,0 +1,206 @@ +package org.branulf.toolbox.mixin.showenchants; + +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.ItemEnchantmentsComponent; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.Enchantments; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.registry.tag.EnchantmentTags; +import net.minecraft.text.Text; +import net.minecraft.registry.RegistryKey; +import net.minecraft.util.Identifier; +import org.branulf.toolbox.Main; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; +import java.util.Optional; +import java.util.regex.Pattern; +import com.google.common.collect.Lists; + +@Mixin(DrawContext.class) +public abstract class DrawContextMixin { + + /** + * 功能参考自Fabrication + */ + + private static final Pattern COLOR_CODE_PATTERN = Pattern.compile("§[0-9A-FK-ORa-fk-or]"); + private static final Pattern INVISIBLE_CHARS = Pattern.compile("[\\p{Cf}\\p{Co}\\p{Cn}\\u2006]"); + + @Shadow @Final private MatrixStack matrices; + + @Shadow + public abstract int drawText(TextRenderer textRenderer, Text text, int x, int y, int color, boolean shadow); + + @Inject( + method = "drawStackOverlay(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V", + at = @At("TAIL") + ) + private void onRenderItemOverlay(TextRenderer renderer, ItemStack stack, int x, int y, String countLabel, CallbackInfo ci) { + if (!Main.getConfig().showEnchants.enabled) { + return; + } + + if (stack == null) return; + + // 附魔书 + if (stack.getItem() == Items.ENCHANTED_BOOK) { + handleEnchantedBook(stack, renderer, x, y); + return; + } + + // 武器工具 + handleWeaponsAndTools(stack, renderer, x, y); + } + + private void handleEnchantedBook(ItemStack stack, TextRenderer renderer, int x, int y) { + ItemEnchantmentsComponent enchants = stack.get(DataComponentTypes.STORED_ENCHANTMENTS); + if (enchants == null || enchants.isEmpty()) return; + + List> valid = Lists.newArrayList(enchants.getEnchantments()); + if (valid.isEmpty()) return; + + int index = (int) ((System.currentTimeMillis() / 1000) % valid.size()); + RegistryEntry enchant = valid.get(index); + + String name = enchant.value().description().getString(); + String firstChar = getFirstVisibleChar(name); + + if (firstChar.isEmpty()) { + firstChar = getFallbackChar(enchant); + } + + if (!firstChar.isEmpty()) { + matrices.push(); + matrices.translate(0, 0, 200); + + int color = enchant.isIn(EnchantmentTags.CURSE) ? 0xFFFF5555 : + enchant.isIn(EnchantmentTags.TREASURE) ? 0xFF55FFFF : 0xFFFFFFFF; + + this.drawText(renderer, Text.literal(firstChar), x + 2, y + 9, color, true); + matrices.pop(); + } + } + + private void handleWeaponsAndTools(ItemStack stack, TextRenderer renderer, int x, int y) { + ItemEnchantmentsComponent enchants = stack.get(DataComponentTypes.ENCHANTMENTS); + if (enchants == null || enchants.isEmpty()) return; + + List> enchantments = Lists.newArrayList(enchants.getEnchantments()); + if (enchantments.isEmpty()) return; + + RegistryEntry primaryEnchant = findPrimaryEnchantment(enchantments); + if (primaryEnchant == null) return; + + String name = primaryEnchant.value().description().getString(); + String firstChar = getFirstVisibleChar(name); + + if (firstChar.isEmpty()) { + firstChar = getFallbackChar(primaryEnchant); + } + + if (!firstChar.isEmpty()) { + matrices.push(); + matrices.translate(0, 0, 200); + + int color = primaryEnchant.isIn(EnchantmentTags.CURSE) ? 0xFFFF5555 : + primaryEnchant.isIn(EnchantmentTags.TREASURE) ? 0xFF55FFFF : 0xFFFF55FF; + + this.drawText(renderer, Text.literal(firstChar), x + 2, y + 9, color, true); + matrices.pop(); + } + } + + private RegistryEntry findPrimaryEnchantment(List> enchantments) { + // 武器 + for (RegistryEntry entry : enchantments) { + Optional> key = entry.getKey(); + if (key.isPresent()) { + Identifier id = key.get().getValue(); + if (id.equals(Enchantments.SHARPNESS.getValue()) || + id.equals(Enchantments.SMITE.getValue()) || + id.equals(Enchantments.BANE_OF_ARTHROPODS.getValue())) { + return entry; + } + } + } + + // 工具 + for (RegistryEntry entry : enchantments) { + Optional> key = entry.getKey(); + if (key.isPresent()) { + Identifier id = key.get().getValue(); + if (id.equals(Enchantments.SILK_TOUCH.getValue()) || + id.equals(Enchantments.FORTUNE.getValue())) { + return entry; + } + } + } + + // 杂七杂八 + for (RegistryEntry entry : enchantments) { + Optional> key = entry.getKey(); + if (key.isPresent()) { + Identifier id = key.get().getValue(); + if (id.equals(Enchantments.RIPTIDE.getValue()) || + id.equals(Enchantments.LOYALTY.getValue()) || + id.equals(Enchantments.CHANNELING.getValue())) { + return entry; + } + } + } + + return null; + } + + + private String getFirstVisibleChar(String str) { + if (str == null || str.isEmpty()) { + return ""; + } + + str = COLOR_CODE_PATTERN.matcher(str).replaceAll(""); + str = INVISIBLE_CHARS.matcher(str).replaceAll("").trim(); + + if (str.isEmpty()) { + return ""; + } + + int[] codePoints = str.codePoints().toArray(); + for (int codePoint : codePoints) { + if (!Character.isISOControl(codePoint) && + !Character.isWhitespace(codePoint) && + !isPrivateUseCharacter(codePoint)) { + return new String(Character.toChars(codePoint)); + } + } + return ""; + } + + private boolean isPrivateUseCharacter(int codePoint) { + return (codePoint >= 0xE000 && codePoint <= 0xF8FF) || + (codePoint >= 0xF0000 && codePoint <= 0xFFFFD) || + (codePoint >= 0x100000 && codePoint <= 0x10FFFD); + } + + private String getFallbackChar(RegistryEntry enchant) { + Optional> key = enchant.getKey(); + if (key.isPresent()) { + String id = key.get().getValue().getPath(); + if (!id.isEmpty()) { + return id.substring(0, 1).toUpperCase(); + } + } + return "?"; + } +} diff --git a/src/main/resources/assets/branulf_toolbox/lang/en_us.json b/src/main/resources/assets/branulf_toolbox/lang/en_us.json index 7e7a911..d23d7f0 100644 --- a/src/main/resources/assets/branulf_toolbox/lang/en_us.json +++ b/src/main/resources/assets/branulf_toolbox/lang/en_us.json @@ -15,6 +15,7 @@ "text.autoconfig.branulf_toolbox.category.elytraboost_settings": "Elytra Boost Settings", "text.autoconfig.branulf_toolbox.category.player_detector_settings": "Player Detector Settings", "text.autoconfig.branulf_toolbox.category.damage_logger_settings": "Damage Logger Settings", + "text.autoconfig.branulf_toolbox.category.show_enchants_settings": "Show Enchants Settings", "gui.branulf_toolbox.autocrossbow.title": "Auto Crossbow", "gui.branulf_toolbox.autocrossbow.enabled_on": "Enable Auto Crossbow", @@ -92,5 +93,9 @@ "gui.branulf_toolbox.damage_logger.open_folder": "Open Log Folder", "text.autoconfig.branulf_toolbox.option.damageLogger.enabled": "Enable Damage Logger", "text.autoconfig.branulf_toolbox.option.damageLogger.rememberState": "Remember Logging State", - "text.autoconfig.branulf_toolbox.option.damageLogger.rememberState.@Tooltip": "If enabled, the damage logger will resume logging automatically when you restart the game if it was active. If disabled, it will turn off on game exit." + "text.autoconfig.branulf_toolbox.option.damageLogger.rememberState.@Tooltip": "If enabled, the damage logger will resume logging automatically when you restart the game if it was active. If disabled, it will turn off on game exit.", + + "text.autoconfig.branulf_toolbox.option.showEnchants.enabled": "Enable Show Enchants", + "text.autoconfig.branulf_toolbox.option.showEnchants.enabled.@Tooltip[0]": "If enabled, the first character of the main enchantment will be displayed on item stacks.", + "text.autoconfig.branulf_toolbox.option.showEnchants.enabled.@Tooltip[1]": "Reference from Fabrication" } diff --git a/src/main/resources/assets/branulf_toolbox/lang/zh_cn.json b/src/main/resources/assets/branulf_toolbox/lang/zh_cn.json index 0907826..1fdf9c3 100644 --- a/src/main/resources/assets/branulf_toolbox/lang/zh_cn.json +++ b/src/main/resources/assets/branulf_toolbox/lang/zh_cn.json @@ -10,11 +10,12 @@ "text.autoconfig.branulf_toolbox.title": "BRanulf的实用工具箱配置", "text.autoconfig.branulf_toolbox.category.autocrossbow_settings": "诸葛连弩设置", - "text.autoconfig.branulf_toolbox.category.scrafitipty_plus_settings": "Scrafitipty Plus 设置", + "text.autoconfig.branulf_toolbox.category.scrafitipty_plus_settings": "WebSocket设置", "text.autoconfig.branulf_toolbox.category.crazylook_settings": "摇晃挂机设置", - "text.autoconfig.branulf_toolbox.category.elytraboost_settings": "鞘翅推进优化设置", - "text.autoconfig.branulf_toolbox.category.player_detector_settings": "玩家探测器设置", + "text.autoconfig.branulf_toolbox.category.elytraboost_settings": "鞘翅优化设置", + "text.autoconfig.branulf_toolbox.category.player_detector_settings": "玩家探测设置", "text.autoconfig.branulf_toolbox.category.damage_logger_settings": "伤害记录设置", + "text.autoconfig.branulf_toolbox.category.show_enchants_settings": "显示附魔设置", "gui.branulf_toolbox.autocrossbow.title": "诸葛连弩", "gui.branulf_toolbox.autocrossbow.enabled_on": "启用诸葛连弩", @@ -92,5 +93,9 @@ "gui.branulf_toolbox.damage_logger.open_folder": "打开日志文件夹", "text.autoconfig.branulf_toolbox.option.damageLogger.enabled": "启用伤害记录", "text.autoconfig.branulf_toolbox.option.damageLogger.rememberState": "记住开关状态", - "text.autoconfig.branulf_toolbox.option.damageLogger.rememberState.@Tooltip": "如果启用,当您退出游戏时,伤害记录功能将保存当前状态并在下次进入游戏时自动恢复。如果禁用,退出游戏后将关闭伤害记录功能。" + "text.autoconfig.branulf_toolbox.option.damageLogger.rememberState.@Tooltip": "如果启用,当您退出游戏时,伤害记录功能将保存当前状态并在下次进入游戏时自动恢复。如果禁用,退出游戏后将关闭伤害记录功能。", + + "text.autoconfig.branulf_toolbox.option.showEnchants.enabled": "启用显示附魔", + "text.autoconfig.branulf_toolbox.option.showEnchants.enabled.@Tooltip[0]": "如果启用,物品堆上将显示主要附魔的第一个字符。", + "text.autoconfig.branulf_toolbox.option.showEnchants.enabled.@Tooltip[1]": "参考自Fabrication" } diff --git a/src/main/resources/branulf_toolbox.mixins.json b/src/main/resources/branulf_toolbox.mixins.json new file mode 100644 index 0000000..1684e3a --- /dev/null +++ b/src/main/resources/branulf_toolbox.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "org.branulf.toolbox.mixin.showenchants", + "compatibilityLevel": "JAVA_21", + "mixins": [], + "client": [ + "DrawContextMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index e83dfd0..8707bd4 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -22,6 +22,9 @@ "org.branulf.toolbox.ModMenuIntegration" ] }, + "mixins": [ + "branulf_toolbox.mixins.json" + ], "depends": { "fabricloader": ">=${loader_version}", "fabric": "*",