舍弃按钮,改用点击编码按键自动上传
This commit is contained in:
parent
ad8a7ac930
commit
48bd05576c
|
|
@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G
|
||||||
loom.platform = forge
|
loom.platform = forge
|
||||||
|
|
||||||
# Mod properties
|
# Mod properties
|
||||||
mod_version = 1.2.0-a
|
mod_version = 1.2.1
|
||||||
maven_group = com.extendedae_plus
|
maven_group = com.extendedae_plus
|
||||||
archives_name = extendedae_plus
|
archives_name = extendedae_plus
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,18 @@
|
||||||
package com.extendedae_plus.mixin;
|
package com.extendedae_plus.mixin;
|
||||||
|
|
||||||
import appeng.menu.me.items.PatternEncodingTermMenu;
|
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.IActionHolder;
|
||||||
import com.glodblock.github.glodium.network.packet.sync.Paras;
|
import com.glodblock.github.glodium.network.packet.sync.Paras;
|
||||||
|
import com.extendedae_plus.util.ExtendedAEPatternUploadUtil;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
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.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
@ -29,39 +33,47 @@ public abstract class ContainerPatternEncodingTermMenuMixin implements IActionHo
|
||||||
@Unique
|
@Unique
|
||||||
private Player epp$player;
|
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)
|
// 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)
|
@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) {
|
private void epp$ctorA(int id, net.minecraft.world.entity.player.Inventory ip, appeng.helpers.IPatternTerminalMenuHost host, CallbackInfo ci) {
|
||||||
this.epp$player = ip.player;
|
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)
|
// 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)
|
@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) {
|
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;
|
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
|
@NotNull
|
||||||
|
|
@ -69,4 +81,33 @@ public abstract class ContainerPatternEncodingTermMenuMixin implements IActionHo
|
||||||
public Map<String, Consumer<Paras>> getActionMap() {
|
public Map<String, Consumer<Paras>> getActionMap() {
|
||||||
return this.actions;
|
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;
|
package com.extendedae_plus.mixin;
|
||||||
|
|
||||||
import appeng.client.gui.me.items.PatternEncodingTermScreen;
|
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.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;
|
// 保留空的 Mixin 外壳,不再注入任何“上传到矩阵”相关逻辑或按钮
|
||||||
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(PatternEncodingTermScreen.class)
|
@Mixin(PatternEncodingTermScreen.class)
|
||||||
public abstract class GuiPatternEncodingTermMixin<C extends PatternEncodingTermMenu> {
|
public abstract class GuiPatternEncodingTermMixin {
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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",
|
"ContainerUWirelessExPatternTerminalMixin",
|
||||||
"TileExPatternProviderMixin",
|
"TileExPatternProviderMixin",
|
||||||
"PartExPatternProviderMixin",
|
"PartExPatternProviderMixin",
|
||||||
|
"PatternEncodingTermMenuMixin",
|
||||||
"ContainerPatternEncodingTermMenuMixin",
|
"ContainerPatternEncodingTermMenuMixin",
|
||||||
"accessor.MEStorageMenuAccessor",
|
"accessor.MEStorageMenuAccessor",
|
||||||
"accessor.PatternEncodingTermMenuAccessor"
|
"accessor.PatternEncodingTermMenuAccessor"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user