This commit is contained in:
BRanulf_Explode 2025-08-24 18:56:19 +08:00
parent 8a64b024ef
commit fcc7cf4659
8 changed files with 250 additions and 6 deletions

View File

@ -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

View File

@ -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;
}
}

View File

@ -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 "错误重生点爆炸伤害";

View File

@ -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<RegistryEntry<Enchantment>> valid = Lists.newArrayList(enchants.getEnchantments());
if (valid.isEmpty()) return;
int index = (int) ((System.currentTimeMillis() / 1000) % valid.size());
RegistryEntry<Enchantment> 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<RegistryEntry<Enchantment>> enchantments = Lists.newArrayList(enchants.getEnchantments());
if (enchantments.isEmpty()) return;
RegistryEntry<Enchantment> 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<Enchantment> findPrimaryEnchantment(List<RegistryEntry<Enchantment>> enchantments) {
// 武器
for (RegistryEntry<Enchantment> entry : enchantments) {
Optional<RegistryKey<Enchantment>> 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<Enchantment> entry : enchantments) {
Optional<RegistryKey<Enchantment>> 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<Enchantment> entry : enchantments) {
Optional<RegistryKey<Enchantment>> 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<Enchantment> enchant) {
Optional<RegistryKey<Enchantment>> key = enchant.getKey();
if (key.isPresent()) {
String id = key.get().getValue().getPath();
if (!id.isEmpty()) {
return id.substring(0, 1).toUpperCase();
}
}
return "?";
}
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -0,0 +1,13 @@
{
"required": true,
"minVersion": "0.8",
"package": "org.branulf.toolbox.mixin.showenchants",
"compatibilityLevel": "JAVA_21",
"mixins": [],
"client": [
"DrawContextMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@ -22,6 +22,9 @@
"org.branulf.toolbox.ModMenuIntegration"
]
},
"mixins": [
"branulf_toolbox.mixins.json"
],
"depends": {
"fabricloader": ">=${loader_version}",
"fabric": "*",