舍弃按钮,改用点击编码按键自动上传
This commit is contained in:
parent
ad8a7ac930
commit
48bd05576c
|
|
@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G
|
|||
loom.platform = forge
|
||||
|
||||
# Mod properties
|
||||
mod_version = 1.2.0-a
|
||||
mod_version = 1.2.1
|
||||
maven_group = com.extendedae_plus
|
||||
archives_name = extendedae_plus
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,18 @@
|
|||
package com.extendedae_plus.mixin;
|
||||
|
||||
import appeng.menu.me.items.PatternEncodingTermMenu;
|
||||
import com.extendedae_plus.util.ExtendedAEPatternUploadUtil;
|
||||
import appeng.menu.slot.RestrictedInputSlot;
|
||||
import appeng.api.crafting.PatternDetailsHelper;
|
||||
import appeng.parts.encoding.EncodingMode;
|
||||
import com.glodblock.github.glodium.network.packet.sync.IActionHolder;
|
||||
import com.glodblock.github.glodium.network.packet.sync.Paras;
|
||||
import com.extendedae_plus.util.ExtendedAEPatternUploadUtil;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
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;
|
||||
|
|
@ -29,39 +33,47 @@ public abstract class ContainerPatternEncodingTermMenuMixin implements IActionHo
|
|||
@Unique
|
||||
private Player epp$player;
|
||||
|
||||
@Shadow(remap = false)
|
||||
private RestrictedInputSlot encodedPatternSlot;
|
||||
|
||||
@Unique
|
||||
private void epp$scheduleUploadWithRetry(ServerPlayer sp, PatternEncodingTermMenu menu, int attemptsLeft) {
|
||||
sp.server.execute(() -> {
|
||||
try {
|
||||
if (attemptsLeft < 0) {
|
||||
return;
|
||||
}
|
||||
var stack = this.encodedPatternSlot != null ? this.encodedPatternSlot.getItem() : net.minecraft.world.item.ItemStack.EMPTY;
|
||||
if (stack != null && !stack.isEmpty() && PatternDetailsHelper.isEncodedPattern(stack)) {
|
||||
System.out.println("[EAE+][Server] Auto-upload crafting pattern after encode.");
|
||||
ExtendedAEPatternUploadUtil.uploadFromEncodingMenuToMatrix(sp, menu);
|
||||
} else {
|
||||
// 槽位可能尚未同步到位,继续下一 tick 重试
|
||||
if (attemptsLeft > 0) {
|
||||
epp$scheduleUploadWithRetry(sp, menu, attemptsLeft - 1);
|
||||
} else {
|
||||
System.out.println("[EAE+][Server] Auto-upload aborted: encoded slot still empty or not encoded after retries.");
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[EAE+][Server] Auto-upload after encode failed: " + t);
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// AE2 终端主构造:PatternEncodingTermMenu(int id, Inventory ip, IPatternTerminalMenuHost host)
|
||||
@Inject(method = "<init>(ILnet/minecraft/world/entity/player/Inventory;Lappeng/helpers/IPatternTerminalMenuHost;)V", at = @At("TAIL"), remap = false)
|
||||
private void epp$ctorA(int id, net.minecraft.world.entity.player.Inventory ip, appeng.helpers.IPatternTerminalMenuHost host, CallbackInfo ci) {
|
||||
this.epp$player = ip.player;
|
||||
// 注册动作:无参,由服务端直接读 encoded 槽位。
|
||||
System.out.println("[EAE+][Server] Register action 'upload_to_matrix' for PatternEncodingTermMenu ctorA");
|
||||
this.actions.put("upload_to_matrix", p -> {
|
||||
try {
|
||||
var sp = (ServerPlayer) this.epp$player;
|
||||
System.out.println("[EAE+][Server] Handle action 'upload_to_matrix' from " + sp.getGameProfile().getName());
|
||||
ExtendedAEPatternUploadUtil.uploadFromEncodingMenuToMatrix(sp, (PatternEncodingTermMenu) (Object) this);
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[EAE+][Server] Exception in 'upload_to_matrix': " + t);
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
// 不再注册任何上传相关动作
|
||||
}
|
||||
|
||||
// AE2 另一个构造:PatternEncodingTermMenu(MenuType, int, Inventory, IPatternTerminalMenuHost, boolean)
|
||||
@Inject(method = "<init>(Lnet/minecraft/world/inventory/MenuType;ILnet/minecraft/world/entity/player/Inventory;Lappeng/helpers/IPatternTerminalMenuHost;Z)V", at = @At("TAIL"), remap = false)
|
||||
private void epp$ctorB(net.minecraft.world.inventory.MenuType<?> menuType, int id, net.minecraft.world.entity.player.Inventory ip, appeng.helpers.IPatternTerminalMenuHost host, boolean bindInventory, CallbackInfo ci) {
|
||||
this.epp$player = ip.player;
|
||||
System.out.println("[EAE+][Server] Register action 'upload_to_matrix' for PatternEncodingTermMenu ctorB");
|
||||
this.actions.put("upload_to_matrix", p -> {
|
||||
try {
|
||||
var sp = (ServerPlayer) this.epp$player;
|
||||
System.out.println("[EAE+][Server] Handle action 'upload_to_matrix' from " + sp.getGameProfile().getName());
|
||||
ExtendedAEPatternUploadUtil.uploadFromEncodingMenuToMatrix(sp, (PatternEncodingTermMenu) (Object) this);
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[EAE+][Server] Exception in 'upload_to_matrix': " + t);
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
// 不再注册任何上传相关动作
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
|
@ -69,4 +81,33 @@ public abstract class ContainerPatternEncodingTermMenuMixin implements IActionHo
|
|||
public Map<String, Consumer<Paras>> getActionMap() {
|
||||
return this.actions;
|
||||
}
|
||||
|
||||
// 服务器端:在 encode() 执行完毕后,如果已编码槽位存在样板且当前为“合成模式”,则上传到装配矩阵
|
||||
@Inject(method = "encode", at = @At("TAIL"), remap = false)
|
||||
private void epp$serverUploadAfterEncode(CallbackInfo ci) {
|
||||
try {
|
||||
if (!(this.epp$player instanceof ServerPlayer sp)) {
|
||||
return; // 仅服务器执行
|
||||
}
|
||||
var menu = (PatternEncodingTermMenu) (Object) this;
|
||||
if (menu.getMode() != EncodingMode.CRAFTING) {
|
||||
return; // 只处理合成样板
|
||||
}
|
||||
if (this.encodedPatternSlot == null) {
|
||||
return;
|
||||
}
|
||||
var stack = this.encodedPatternSlot.getItem();
|
||||
if (stack == null || stack.isEmpty()) {
|
||||
return; // 没有编码样板
|
||||
}
|
||||
if (!PatternDetailsHelper.isEncodedPattern(stack)) {
|
||||
return; // 不是编码样板
|
||||
}
|
||||
// 为兼容整合包中可能出现的延后写槽位/同步,增加多次重试(共 5 次,每次间隔 1 tick)
|
||||
epp$scheduleUploadWithRetry(sp, menu, 5);
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[EAE+][Server] epp$serverUploadAfterEncode error: " + t);
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,145 +1,9 @@
|
|||
package com.extendedae_plus.mixin;
|
||||
|
||||
import appeng.client.gui.me.items.PatternEncodingTermScreen;
|
||||
import appeng.client.gui.widgets.IconButton;
|
||||
import appeng.client.gui.Icon;
|
||||
import appeng.client.gui.style.ScreenStyle;
|
||||
import appeng.menu.me.items.PatternEncodingTermMenu;
|
||||
import appeng.parts.encoding.EncodingMode;
|
||||
import appeng.menu.SlotSemantics;
|
||||
import net.minecraft.client.gui.components.Tooltip;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.glodblock.github.extendedae.network.EPPNetworkHandler;
|
||||
import com.glodblock.github.glodium.network.packet.CGenericPacket;
|
||||
import com.extendedae_plus.mixin.accessor.ScreenAccessor;
|
||||
import com.extendedae_plus.mixin.accessor.AEBaseScreenAccessor;
|
||||
|
||||
/**
|
||||
* 在 AE2 的 PatternEncodingTermScreen 界面中,给编码按钮旁添加一个“上传到矩阵”按钮。
|
||||
* 客户端点击后,使用 ExtendedAE 的网络通道发送通用数据包到服务端,由容器 Mixin 处理。
|
||||
*/
|
||||
// 保留空的 Mixin 外壳,不再注入任何“上传到矩阵”相关逻辑或按钮
|
||||
@Mixin(PatternEncodingTermScreen.class)
|
||||
public abstract class GuiPatternEncodingTermMixin<C extends PatternEncodingTermMenu> {
|
||||
|
||||
@Unique
|
||||
private IconButton epp$uploadButton;
|
||||
@Unique
|
||||
private boolean epp$addedWidget = false;
|
||||
@Unique
|
||||
private boolean epp$usingToolbar = false;
|
||||
|
||||
// 在构造函数尾部创建按钮实例并加入普通部件列表
|
||||
@Inject(method = "<init>", at = @At("TAIL"), remap = false)
|
||||
private void epp$onInit(C menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
|
||||
// 选择一个合适的图标占位(AE2 暂无显式“上传”图标,这里先用 PATTERN_ACCESS_SHOW)
|
||||
this.epp$uploadButton = new IconButton(b -> {
|
||||
// 直接发送无参动作,服务端容器会根据当前 encoded 槽位处理
|
||||
System.out.println("[EAE+][Client] Click upload button -> send CGenericPacket('upload_to_matrix')");
|
||||
try {
|
||||
var mc = net.minecraft.client.Minecraft.getInstance();
|
||||
var cm = mc.player != null ? mc.player.containerMenu : null;
|
||||
System.out.println("[EAE+][Client] Current container: " + (cm == null ? "null" : cm.getClass().getName()));
|
||||
if (cm instanceof com.glodblock.github.glodium.network.packet.sync.IActionHolder ah) {
|
||||
var keys = ah.getActionMap().keySet();
|
||||
System.out.println("[EAE+][Client] IActionHolder detected. actions=" + keys);
|
||||
} else {
|
||||
System.out.println("[EAE+][Client] Current container is NOT IActionHolder");
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[EAE+][Client] Inspect container failed: " + t);
|
||||
}
|
||||
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("upload_to_matrix"));
|
||||
}) {
|
||||
@Override
|
||||
protected Icon getIcon() {
|
||||
return Icon.PATTERN_ACCESS_SHOW;
|
||||
}
|
||||
};
|
||||
this.epp$uploadButton.setTooltip(Tooltip.create(Component.translatable("extendedae_plus.upload_to_matrix")));
|
||||
System.out.println("[EAE+][Client] Created upload button in PatternEncodingTermScreen ctor tail");
|
||||
// 注意:此处不立即添加到 Screen,等到 updateBeforeRender 首帧再添加,避免在构造期调用导致异常
|
||||
this.epp$uploadButton.visible = false; // 初始隐藏,等待定位
|
||||
}
|
||||
|
||||
// 在每帧渲染前定位按钮到“已编码样板槽位”的左侧
|
||||
@Inject(method = "updateBeforeRender", at = @At("TAIL"), remap = false)
|
||||
private void epp$positionUploadButton(CallbackInfo ci) {
|
||||
try {
|
||||
if (this.epp$uploadButton == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 首帧尝试将按钮加入到 Screen 的可渲染部件中
|
||||
if (!this.epp$addedWidget) {
|
||||
try {
|
||||
((ScreenAccessor)(Object)this).epp$invokeAddRenderableWidget(this.epp$uploadButton);
|
||||
this.epp$addedWidget = true;
|
||||
this.epp$usingToolbar = false;
|
||||
System.out.println("[EAE+][Client] Added upload button as normal widget in first updateBeforeRender");
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[EAE+][Client] addRenderableWidget failed, fallback to left toolbar: " + t);
|
||||
try {
|
||||
((AEBaseScreenAccessor)(Object)this).epp$addToLeftToolbar(this.epp$uploadButton);
|
||||
this.epp$addedWidget = true;
|
||||
this.epp$usingToolbar = true;
|
||||
this.epp$uploadButton.visible = true;
|
||||
System.out.println("[EAE+][Client] Fallback added to left toolbar");
|
||||
} catch (Throwable t2) {
|
||||
System.out.println("[EAE+][Client] Fallback addToLeftToolbar also failed: " + t2);
|
||||
// 放弃添加,避免死循环
|
||||
this.epp$addedWidget = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 仅在“合成模式”下显示按钮(与上传逻辑一致)
|
||||
var self = (PatternEncodingTermScreen<?>) (Object) this;
|
||||
var menu = (PatternEncodingTermMenu) self.getMenu();
|
||||
if (menu == null) {
|
||||
return;
|
||||
}
|
||||
boolean craftingMode = menu.getMode() == EncodingMode.CRAFTING;
|
||||
|
||||
Slot encoded = null;
|
||||
for (Slot s : menu.slots) {
|
||||
var sem = menu.getSlotSemantic(s);
|
||||
if (sem == SlotSemantics.ENCODED_PATTERN) {
|
||||
encoded = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果退回到左侧工具栏显示,则不做定位
|
||||
if (this.epp$usingToolbar) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (craftingMode && encoded != null) {
|
||||
int slotX = self.getGuiLeft() + encoded.x;
|
||||
int slotY = self.getGuiTop() + encoded.y;
|
||||
int bw = this.epp$uploadButton.getWidth();
|
||||
int bh = this.epp$uploadButton.getHeight();
|
||||
int gap = 3;
|
||||
|
||||
this.epp$uploadButton.setX(slotX - gap - bw);
|
||||
this.epp$uploadButton.setY(slotY + (18 - bh) / 2);
|
||||
this.epp$uploadButton.visible = true;
|
||||
// 可选:当槽位有编码图样时启用
|
||||
this.epp$uploadButton.active = !encoded.getItem().isEmpty();
|
||||
} else {
|
||||
this.epp$uploadButton.visible = false;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[EAE+][Client] updateBeforeRender positioning failed: " + t);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class GuiPatternEncodingTermMixin {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
package com.extendedae_plus.mixin.accessor;
|
||||
|
||||
/**
|
||||
* 客户端在点击“编写样板”时记录一个待上传标记,
|
||||
* 当客户端检测到已编码样板槽位被服务器回传填充后,再发送上传请求。
|
||||
*/
|
||||
public interface IClientEncodeUploadMarker {
|
||||
boolean epp$getClientUploadAfterEncode();
|
||||
void epp$setClientUploadAfterEncode(boolean v);
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
"ContainerUWirelessExPatternTerminalMixin",
|
||||
"TileExPatternProviderMixin",
|
||||
"PartExPatternProviderMixin",
|
||||
"PatternEncodingTermMenuMixin",
|
||||
"ContainerPatternEncodingTermMenuMixin",
|
||||
"accessor.MEStorageMenuAccessor",
|
||||
"accessor.PatternEncodingTermMenuAccessor"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user