修复改用网络发包,兼容多人游戏(删除冗余代码)

This commit is contained in:
GaLi 2025-08-11 11:58:27 +08:00
parent 16e929470b
commit 3eeabc37c2
12 changed files with 2 additions and 635 deletions

View File

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

View File

@ -1,18 +0,0 @@
package com.extendedae_plus;
import net.minecraftforge.fml.common.Mod;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@Mod(ExampleMod.MOD_ID)
public final class ExampleMod {
public static final String MOD_ID = "extendedae_plus";
public static final Logger LOGGER = LogManager.getLogger(MOD_ID);
public ExampleMod() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like registries and resources) may still be uninitialized.
// Proceed with mild caution.
LOGGER.info("ExtendedAE Plus mod initialized! Pattern provider slots will be increased to 108.");
}
}

View File

@ -1,6 +1,4 @@
package com.extendedae_plus;
import com.extendedae_plus.network.NetworkHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.common.Mod;
@ -29,7 +27,6 @@ public class ExtendedAEPlus {
* 通用初始化设置
*/
private void commonSetup(final FMLCommonSetupEvent event) {
// 注册网络处理器确保在注册窗口关闭前完成
event.enqueueWork(NetworkHandler::initialize);
// 现已改用 ExtendedAE EPPNetworkHandler + CGenericPacket无需自定义网络初始化
}
}

View File

@ -1,59 +0,0 @@
package com.extendedae_plus.client.gui;
import net.minecraft.client.gui.components.Button;
import net.minecraft.network.chat.Component;
import appeng.client.gui.Icon;
import appeng.client.gui.widgets.IconButton;
/**
* GroupHeader选择按钮
* 用于在样板访问终端中标记GroupHeaderRow的Ischooiceable状态
*/
public class GroupHeaderChoiceButton extends IconButton {
private boolean isChoiceable = false;
private final String groupName;
private final Runnable onChoiceChanged;
public GroupHeaderChoiceButton(String groupName, Runnable onChoiceChanged) {
super(button -> {
GroupHeaderChoiceButton choiceButton = (GroupHeaderChoiceButton) button;
choiceButton.toggleChoice();
});
this.groupName = groupName;
this.onChoiceChanged = onChoiceChanged;
this.setHalfSize(true); // 使用小尺寸按钮
this.setMessage(Component.translatable("gui.extendedae_plus.group_header.choice"));
}
public void toggleChoice() {
this.isChoiceable = !this.isChoiceable;
if (this.onChoiceChanged != null) {
this.onChoiceChanged.run();
}
}
public void setChoiceable(boolean isChoiceable) {
this.isChoiceable = isChoiceable;
}
public boolean isChoiceable() {
return this.isChoiceable;
}
public String getGroupName() {
return this.groupName;
}
@Override
protected Icon getIcon() {
return this.isChoiceable ? Icon.WHITELIST : Icon.BLACKLIST;
}
@Override
public Component getMessage() {
return this.isChoiceable
? Component.translatable("gui.extendedae_plus.group_header.choiceable")
: Component.translatable("gui.extendedae_plus.group_header.not_choiceable");
}
}

View File

@ -1,28 +0,0 @@
package com.extendedae_plus.client.gui;
import appeng.client.gui.style.Blitter;
import net.minecraft.resources.ResourceLocation;
/**
* PatternBetter功能的图标定义
* 复刻自PatternBetter模组的NewIcon类
*/
public class PatternBetterIcons {
private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath("extendedae_plus", "textures/gui/pattern_better_icons.png");
public static final Blitter MULTIPLY2;
public static final Blitter DIVIDE2;
public static final Blitter MULTIPLY5;
public static final Blitter DIVIDE5;
public static final Blitter MULTIPLY10;
public static final Blitter DIVIDE10;
static {
MULTIPLY2 = Blitter.texture(TEXTURE, 64, 64).src(32, 0, 16, 16);
DIVIDE2 = Blitter.texture(TEXTURE, 64, 64).src(48, 0, 16, 16);
MULTIPLY5 = Blitter.texture(TEXTURE, 64, 64).src(0, 0, 16, 16);
DIVIDE5 = Blitter.texture(TEXTURE, 64, 64).src(16, 0, 16, 16);
MULTIPLY10 = Blitter.texture(TEXTURE, 64, 64).src(0, 16, 16, 16);
DIVIDE10 = Blitter.texture(TEXTURE, 64, 64).src(16, 16, 16, 16);
}
}

View File

@ -1,59 +0,0 @@
package com.extendedae_plus.client.gui;
import net.minecraft.client.gui.components.Button;
import net.minecraft.network.chat.Component;
import appeng.client.gui.Icon;
import appeng.client.gui.widgets.IconButton;
/**
* 样板供应器选择按钮
* 用于在样板访问终端中标记选中的样板供应器
*/
public class PatternProviderSelectionButton extends IconButton {
private boolean selected = false;
private final long serverId;
private final Runnable onSelectionChanged;
public PatternProviderSelectionButton(long serverId, Runnable onSelectionChanged) {
super(button -> {
PatternProviderSelectionButton selectionButton = (PatternProviderSelectionButton) button;
selectionButton.toggleSelection();
});
this.serverId = serverId;
this.onSelectionChanged = onSelectionChanged;
this.setHalfSize(true); // 使用小尺寸按钮
this.setMessage(Component.translatable("gui.extendedae_plus.pattern_provider.select"));
}
public void toggleSelection() {
this.selected = !this.selected;
if (this.onSelectionChanged != null) {
this.onSelectionChanged.run();
}
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public boolean isSelected() {
return this.selected;
}
public long getServerId() {
return this.serverId;
}
@Override
protected Icon getIcon() {
return this.selected ? Icon.VALID : Icon.INVALID;
}
@Override
public Component getMessage() {
return this.selected
? Component.translatable("gui.extendedae_plus.pattern_provider.selected")
: Component.translatable("gui.extendedae_plus.pattern_provider.unselected");
}
}

View File

@ -1,97 +0,0 @@
package com.extendedae_plus.network;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.simple.SimpleChannel;
/**
* 网络处理器
* 管理ExtendedAE Plus的所有网络通信
*/
public class NetworkHandler {
private static final String PROTOCOL_VERSION = "1";
private static SimpleChannel INSTANCE;
private static int packetId = 0;
private static boolean registered = false;
/**
* 在合法的注册阶段创建通道可重复调用幂等
*/
private static void initChannel() {
if (INSTANCE == null) {
INSTANCE = NetworkRegistry.newSimpleChannel(
new ResourceLocation("extendedae_plus", "main"),
() -> PROTOCOL_VERSION,
PROTOCOL_VERSION::equals,
PROTOCOL_VERSION::equals
);
}
}
/**
* Mod 早期调用确保在注册窗口关闭前完成通道与包注册
*/
public static void initialize() {
if (!registered) {
initChannel();
registerPackets();
}
}
/**
* 注册所有网络包
*/
public static void registerPackets() {
if (registered) return;
initChannel();
// 样板上传请求包客户端 -> 服务器
INSTANCE.messageBuilder(PatternUploadPacket.class, packetId++, NetworkDirection.PLAY_TO_SERVER)
.decoder(PatternUploadPacket::decode)
.encoder(PatternUploadPacket::encode)
.consumerMainThread(PatternUploadPacket::handle)
.add();
// 样板上传结果包服务器 -> 客户端
INSTANCE.messageBuilder(PatternUploadResultPacket.class, packetId++, NetworkDirection.PLAY_TO_CLIENT)
.decoder(PatternUploadResultPacket::decode)
.encoder(PatternUploadResultPacket::encode)
.consumerMainThread(PatternUploadResultPacket::handle)
.add();
// 样板缩放请求包客户端 -> 服务器
INSTANCE.messageBuilder(PatternScalingPacket.class, packetId++, NetworkDirection.PLAY_TO_SERVER)
.decoder(PatternScalingPacket::decode)
.encoder(PatternScalingPacket::encode)
.consumerMainThread(PatternScalingPacket::handle)
.add();
// 样板缩放结果包服务器 -> 客户端
INSTANCE.messageBuilder(PatternScalingResultPacket.class, packetId++, NetworkDirection.PLAY_TO_CLIENT)
.decoder(PatternScalingResultPacket::decode)
.encoder(PatternScalingResultPacket::encode)
.consumerMainThread(PatternScalingResultPacket::handle)
.add();
registered = true;
}
/**
* 发送包到服务器
*/
public static void sendToServer(Object packet) {
// 如果出现 null说明初始化阶段未被调用避免在锁定后临时创建通道
if (INSTANCE == null) throw new IllegalStateException("Network channel not initialized");
INSTANCE.sendToServer(packet);
}
/**
* 发送包到指定客户端
*/
public static void sendToClient(Object packet, ServerPlayer player) {
if (INSTANCE == null) throw new IllegalStateException("Network channel not initialized");
INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), packet);
}
}

View File

@ -1,127 +0,0 @@
package com.extendedae_plus.network;
import com.extendedae_plus.util.PatternProviderDataUtil;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkEvent;
import appeng.helpers.patternprovider.PatternProviderLogic;
import appeng.menu.me.common.MEStorageMenu;
import java.util.function.Supplier;
/**
* 样板缩放网络包
* 用于从客户端发送样板倍增/除法请求到服务器
*/
public class PatternScalingPacket {
public enum ScalingType {
MULTIPLY, // 倍增
DIVIDE // 除法
}
private final ScalingType scalingType;
private final double scaleFactor;
public PatternScalingPacket(ScalingType scalingType, double scaleFactor) {
this.scalingType = scalingType;
this.scaleFactor = scaleFactor;
}
/**
* 编码数据包
*/
public static void encode(PatternScalingPacket packet, FriendlyByteBuf buffer) {
buffer.writeEnum(packet.scalingType);
buffer.writeDouble(packet.scaleFactor);
}
/**
* 解码数据包
*/
public static PatternScalingPacket decode(FriendlyByteBuf buffer) {
ScalingType scalingType = buffer.readEnum(ScalingType.class);
double scaleFactor = buffer.readDouble();
return new PatternScalingPacket(scalingType, scaleFactor);
}
/**
* 处理数据包服务器端
*/
public static void handle(PatternScalingPacket packet, Supplier<NetworkEvent.Context> contextSupplier) {
NetworkEvent.Context context = contextSupplier.get();
context.enqueueWork(() -> {
ServerPlayer player = context.getSender();
if (player == null) {
return;
}
try {
// 获取玩家当前打开的样板供应器菜单
PatternProviderLogic patternProvider = getCurrentPatternProvider(player);
if (patternProvider == null) {
System.out.println("ExtendedAE Plus: 玩家 " + player.getName().getString() + " 没有打开样板供应器界面");
return;
}
// 在服务器端执行样板缩放操作
PatternProviderDataUtil.PatternScalingResult result;
if (packet.scalingType == ScalingType.MULTIPLY) {
result = PatternProviderDataUtil.duplicatePatternAmountsExtendedAEStyle(patternProvider, packet.scaleFactor);
} else {
result = PatternProviderDataUtil.dividePatternAmounts(patternProvider, packet.scaleFactor);
}
// 发送结果回客户端
if (result != null) {
PatternScalingResultPacket resultPacket = new PatternScalingResultPacket(
result.isSuccessful(),
result.getScaledPatterns(),
result.getFailedPatterns(),
result.getTotalPatterns(),
String.join("; ", result.getErrors())
);
NetworkHandler.sendToClient(resultPacket, player);
System.out.println("ExtendedAE Plus: 服务器端样板缩放完成 - 成功: " + result.getScaledPatterns() + ", 失败: " + result.getFailedPatterns());
}
} catch (Exception e) {
System.out.println("ExtendedAE Plus: 服务器端处理样板缩放时发生错误: " + e.getMessage());
e.printStackTrace();
// 发送错误结果回客户端
PatternScalingResultPacket errorPacket = new PatternScalingResultPacket(
false, 0, 0, 0, "服务器端处理错误: " + e.getMessage()
);
NetworkHandler.sendToClient(errorPacket, player);
}
});
context.setPacketHandled(true);
}
/**
* 获取玩家当前打开的样板供应器逻辑
*/
private static PatternProviderLogic getCurrentPatternProvider(ServerPlayer player) {
try {
if (player.containerMenu != null) {
// 检查是否是样板供应器菜单
String menuClassName = player.containerMenu.getClass().getSimpleName();
if (menuClassName.contains("PatternProvider")) {
// 通过反射获取PatternProviderLogic
var logicField = player.containerMenu.getClass().getDeclaredField("logic");
logicField.setAccessible(true);
Object logic = logicField.get(player.containerMenu);
if (logic instanceof PatternProviderLogic) {
return (PatternProviderLogic) logic;
}
}
}
} catch (Exception e) {
System.out.println("ExtendedAE Plus: 获取样板供应器逻辑时发生错误: " + e.getMessage());
}
return null;
}
}

View File

@ -1,89 +0,0 @@
package com.extendedae_plus.network;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
/**
* 样板缩放结果网络包
* 用于从服务器发送样板缩放操作结果到客户端
*/
public class PatternScalingResultPacket {
private final boolean successful;
private final int scaledPatterns;
private final int failedPatterns;
private final int totalPatterns;
private final String errorMessage;
public PatternScalingResultPacket(boolean successful, int scaledPatterns, int failedPatterns, int totalPatterns, String errorMessage) {
this.successful = successful;
this.scaledPatterns = scaledPatterns;
this.failedPatterns = failedPatterns;
this.totalPatterns = totalPatterns;
this.errorMessage = errorMessage != null ? errorMessage : "";
}
/**
* 编码数据包
*/
public static void encode(PatternScalingResultPacket packet, FriendlyByteBuf buffer) {
buffer.writeBoolean(packet.successful);
buffer.writeInt(packet.scaledPatterns);
buffer.writeInt(packet.failedPatterns);
buffer.writeInt(packet.totalPatterns);
buffer.writeUtf(packet.errorMessage);
}
/**
* 解码数据包
*/
public static PatternScalingResultPacket decode(FriendlyByteBuf buffer) {
boolean successful = buffer.readBoolean();
int scaledPatterns = buffer.readInt();
int failedPatterns = buffer.readInt();
int totalPatterns = buffer.readInt();
String errorMessage = buffer.readUtf();
return new PatternScalingResultPacket(successful, scaledPatterns, failedPatterns, totalPatterns, errorMessage);
}
/**
* 处理数据包客户端
*/
public static void handle(PatternScalingResultPacket packet, Supplier<NetworkEvent.Context> contextSupplier) {
NetworkEvent.Context context = contextSupplier.get();
context.enqueueWork(() -> {
Minecraft minecraft = Minecraft.getInstance();
if (minecraft.player != null) {
// 在客户端显示结果消息
String message;
if (packet.successful) {
if (packet.failedPatterns > 0) {
message = String.format("✅ ExtendedAE Plus: 样板缩放部分成功!成功处理 %d 个样板,跳过 %d 个样板",
packet.scaledPatterns, packet.failedPatterns);
} else {
message = String.format("✅ ExtendedAE Plus: 样板缩放成功!处理了 %d 个样板", packet.scaledPatterns);
}
} else {
message = "❌ ExtendedAE Plus: 样板缩放失败!" +
(packet.errorMessage.isEmpty() ? "" : " 错误: " + packet.errorMessage);
}
// 显示消息到聊天栏和动作栏
minecraft.player.displayClientMessage(Component.literal(message), true);
// 同时输出到控制台用于调试
System.out.println("ExtendedAE Plus 客户端收到结果: " + message);
// 如果有错误信息也输出详细错误
if (!packet.errorMessage.isEmpty() && !packet.successful) {
System.out.println("ExtendedAE Plus 详细错误信息: " + packet.errorMessage);
}
}
});
context.setPacketHandled(true);
}
}

View File

@ -1,71 +0,0 @@
package com.extendedae_plus.network;
import com.extendedae_plus.util.ExtendedAEPatternUploadUtil;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
/**
* 样板上传网络包
* 用于从客户端发送样板上传请求到服务器
*/
public class PatternUploadPacket {
private final int playerSlotIndex;
private final long providerId;
public PatternUploadPacket(int playerSlotIndex, long providerId) {
this.playerSlotIndex = playerSlotIndex;
this.providerId = providerId;
}
/**
* 编码数据包
*/
public static void encode(PatternUploadPacket packet, FriendlyByteBuf buffer) {
buffer.writeInt(packet.playerSlotIndex);
buffer.writeLong(packet.providerId);
}
/**
* 解码数据包
*/
public static PatternUploadPacket decode(FriendlyByteBuf buffer) {
int playerSlotIndex = buffer.readInt();
long providerId = buffer.readLong();
return new PatternUploadPacket(playerSlotIndex, providerId);
}
/**
* 处理数据包在服务器端执行
*/
public static void handle(PatternUploadPacket packet, Supplier<NetworkEvent.Context> contextSupplier) {
NetworkEvent.Context context = contextSupplier.get();
context.enqueueWork(() -> {
// 获取发送数据包的玩家
ServerPlayer player = context.getSender();
if (player != null) {
// 在服务器端执行样板上传
boolean success = ExtendedAEPatternUploadUtil.uploadPatternToProvider(
player,
packet.playerSlotIndex,
packet.providerId
);
// 发送结果反馈给客户端
if (success) {
// 上传成功发送成功反馈包
PatternUploadResultPacket resultPacket = new PatternUploadResultPacket(true, "样板上传成功!");
NetworkHandler.sendToClient(resultPacket, player);
} else {
// 上传失败发送失败反馈包
PatternUploadResultPacket resultPacket = new PatternUploadResultPacket(false, "样板上传失败,请检查供应器状态");
NetworkHandler.sendToClient(resultPacket, player);
}
}
});
context.setPacketHandled(true);
}
}

View File

@ -1,51 +0,0 @@
package com.extendedae_plus.network;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
/**
* 样板上传结果网络包
* 用于从服务器发送上传结果反馈到客户端
*/
public class PatternUploadResultPacket {
private final boolean success;
private final String message;
public PatternUploadResultPacket(boolean success, String message) {
this.success = success;
this.message = message;
}
/**
* 编码数据包
*/
public static void encode(PatternUploadResultPacket packet, FriendlyByteBuf buffer) {
buffer.writeBoolean(packet.success);
buffer.writeUtf(packet.message);
}
/**
* 解码数据包
*/
public static PatternUploadResultPacket decode(FriendlyByteBuf buffer) {
boolean success = buffer.readBoolean();
String message = buffer.readUtf();
return new PatternUploadResultPacket(success, message);
}
/**
* 处理数据包在客户端执行
*/
public static void handle(PatternUploadResultPacket packet, Supplier<NetworkEvent.Context> contextSupplier) {
NetworkEvent.Context context = contextSupplier.get();
context.enqueueWork(() -> {
// 不再在客户端左下角显示上传结果消息保持静默
});
context.setPacketHandled(true);
}
}

View File

@ -1,31 +0,0 @@
package com.extendedae_plus.network;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
public class UpdatePagePacket {
private final int newPage;
public UpdatePagePacket(int newPage) {
this.newPage = newPage;
}
public UpdatePagePacket(FriendlyByteBuf buf) {
this.newPage = buf.readInt();
}
public void encode(FriendlyByteBuf buf) {
buf.writeInt(newPage);
}
public boolean handle(Supplier<NetworkEvent.Context> supplier) {
NetworkEvent.Context context = supplier.get();
context.enqueueWork(() -> {
// 这里处理页码更新逻辑
// 由于我们使用@GuiSync实际上不需要额外的网络处理
});
return true;
}
}