This commit is contained in:
GaLicn 2025-08-18 00:35:35 +08:00
parent 624d5c67cd
commit be4607aecd
3 changed files with 138 additions and 1 deletions

View File

@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G
loom.platform = forge
# Mod properties
mod_version = 1.3.0
mod_version = 1.3.1
maven_group = com.extendedae_plus
archives_name = extendedae_plus

View File

@ -0,0 +1,136 @@
package com.extendedae_plus.mixin.ae2;
import appeng.items.tools.quartz.QuartzCuttingKnifeItem;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.Nameable;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import appeng.api.parts.IPartHost;
import appeng.api.parts.SelectedPart;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/**
* AE2 石英切割刀添加潜行 + 右键 指向世界中的方块/部件如线缆复制其名称到剪贴板
*
* 设计要点参考原类 QuartzCuttingKnifeItem 的写法
* - 原本右键会打开 QuartzKnifeMenu我们在客户端潜行且命中方块时优先拦截并复制名称
* - 名称优先取方块实体的自定义名若实现 Nameable否则使用方块显示名
* - 仅在客户端执行剪贴板操作避免在服务端加载客户端类使用 level.isClientSide() 的分支内访问 Minecraft
*/
@Mixin(value = QuartzCuttingKnifeItem.class, remap = false)
public abstract class QuartzCuttingKnifeItemMixin {
@Inject(method = "use", at = @At("HEAD"), cancellable = true)
private void eap$copyNameOnShiftRightClick(Level level, Player player, InteractionHand hand,
CallbackInfoReturnable<InteractionResultHolder<ItemStack>> cir) {
if (!level.isClientSide()) {
return;
}
if (player == null || !player.isShiftKeyDown()) {
return;
}
// 仅在客户端分支访问 Minecraft 防止服务端类加载问题
Minecraft mc = Minecraft.getInstance();
HitResult hr = mc.hitResult;
if (!(hr instanceof BlockHitResult bhr)) {
return;
}
var pos = bhr.getBlockPos();
var state = level.getBlockState(pos);
if (state == null || state.isAir()) {
return;
}
String name = null;
BlockEntity be = level.getBlockEntity(pos);
// 优先若为 AE2 线缆总线选择命中的具体 Part 名称
if (be instanceof IPartHost partHost) {
SelectedPart sel = partHost.selectPartWorld(bhr.getLocation());
if (sel.part != null) {
var stack = new net.minecraft.world.item.ItemStack(sel.part.getPartItem());
name = stack.getHoverName().getString();
} else if (sel.facade != null) {
var stack = sel.facade.getItemStack();
if (!stack.isEmpty()) {
name = stack.getHoverName().getString();
}
}
}
if (be instanceof Nameable nm) {
var custom = nm.getCustomName();
if (custom != null) {
name = custom.getString();
}
}
if (name == null || name.isBlank()) {
name = state.getBlock().getName().getString();
}
try {
mc.keyboardHandler.setClipboard(name);
// 轻量提示客户端侧不刷屏
player.displayClientMessage(Component.literal("已复制方块名: " + name), true);
} catch (Throwable ignored) {
}
// 拦截默认行为不再打开刀具界面
ItemStack held = player.getItemInHand(hand);
cir.setReturnValue(new InteractionResultHolder<>(InteractionResult.SUCCESS, held));
}
@Inject(method = "useOn", at = @At("HEAD"), cancellable = true)
private void eap$copyNameOnShiftRightClickUseOn(UseOnContext context,
CallbackInfoReturnable<InteractionResult> cir) {
Level level = context.getLevel();
Player player = context.getPlayer();
if (!level.isClientSide() || player == null || !player.isShiftKeyDown()) {
return;
}
var pos = context.getClickedPos();
var state = level.getBlockState(pos);
if (state == null || state.isAir()) {
return;
}
String name = null;
BlockEntity be = level.getBlockEntity(pos);
// 优先若为 AE2 线缆总线选择命中的具体 Part 名称使用点击位置的世界坐标
if (be instanceof IPartHost partHost) {
// RenderBlockOutlineHook 相同基于世界坐标选取部件
SelectedPart sel = partHost.selectPartWorld(context.getClickLocation());
if (sel.part != null) {
var stack = new net.minecraft.world.item.ItemStack(sel.part.getPartItem());
name = stack.getHoverName().getString();
} else if (sel.facade != null) {
var stack = sel.facade.getItemStack();
if (!stack.isEmpty()) {
name = stack.getHoverName().getString();
}
}
}
if (be instanceof Nameable nm) {
var custom = nm.getCustomName();
if (custom != null) {
name = custom.getString();
}
}
if (name == null || name.isBlank()) {
name = state.getBlock().getName().getString();
}
try {
Minecraft.getInstance().keyboardHandler.setClipboard(name);
player.displayClientMessage(Component.literal("已复制方块/部件名: " + name), true);
} catch (Throwable ignored) {
}
// 拦截默认行为
cir.setReturnValue(InteractionResult.SUCCESS);
}
}

View File

@ -11,6 +11,7 @@
"PickFromWirelessMixin",
"PatternEncodingTermScreenMixin",
"jei.EncodePatternTransferHandlerMixin",
"ae2.QuartzCuttingKnifeItemMixin",
"accessor.AEBaseScreenAccessor",
"accessor.AbstractContainerScreenAccessor",
"accessor.ScreenAccessor"