修复使用标签无线收发器时偶现退出游戏无法保存问题

This commit is contained in:
GaLi 2026-03-27 23:34:33 +08:00
parent 87e74eb60e
commit 5d773f1937
6 changed files with 131 additions and 6 deletions

View File

@ -8,6 +8,8 @@ import appeng.blockentity.crafting.CraftingBlockEntity;
import appeng.items.parts.PartModelsHelper; import appeng.items.parts.PartModelsHelper;
import com.extendedae_plus.api.ids.EAPComponents; import com.extendedae_plus.api.ids.EAPComponents;
import com.extendedae_plus.api.storage.InfinityBigIntegerCellHandler; import com.extendedae_plus.api.storage.InfinityBigIntegerCellHandler;
import com.extendedae_plus.ae.wireless.LabelNetworkRegistry;
import com.extendedae_plus.ae.wireless.WirelessMasterRegistry;
import com.extendedae_plus.config.ModConfigs; import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.content.ae2.MirrorPatternProviderBlockEntity; import com.extendedae_plus.content.ae2.MirrorPatternProviderBlockEntity;
import com.extendedae_plus.content.matrix.CrafterCorePlusBlockEntity; import com.extendedae_plus.content.matrix.CrafterCorePlusBlockEntity;
@ -29,6 +31,7 @@ import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.server.ServerStartedEvent; import net.neoforged.neoforge.event.server.ServerStartedEvent;
import net.neoforged.neoforge.event.server.ServerStartingEvent; import net.neoforged.neoforge.event.server.ServerStartingEvent;
import net.neoforged.neoforge.event.server.ServerStoppingEvent;
import net.neoforged.neoforge.event.server.ServerStoppedEvent; import net.neoforged.neoforge.event.server.ServerStoppedEvent;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -42,6 +45,7 @@ public class ExtendedAEPlus {
private static InfinityStorageManager storageManager; private static InfinityStorageManager storageManager;
@Nullable @Nullable
private static MinecraftServer storageManagerServer; private static MinecraftServer storageManagerServer;
private static volatile boolean serverStopping;
public ExtendedAEPlus(IEventBus modEventBus, ModContainer modContainer) { public ExtendedAEPlus(IEventBus modEventBus, ModContainer modContainer) {
modEventBus.addListener(this::commonSetup); modEventBus.addListener(this::commonSetup);
@ -60,6 +64,7 @@ public class ExtendedAEPlus {
EAPComponents.DR.register(modEventBus); EAPComponents.DR.register(modEventBus);
NeoForge.EVENT_BUS.register(this); NeoForge.EVENT_BUS.register(this);
NeoForge.EVENT_BUS.addListener(ExtendedAEPlus::onServerStarted); NeoForge.EVENT_BUS.addListener(ExtendedAEPlus::onServerStarted);
NeoForge.EVENT_BUS.addListener(ExtendedAEPlus::onServerStopping);
NeoForge.EVENT_BUS.addListener(ExtendedAEPlus::onServerStopped); NeoForge.EVENT_BUS.addListener(ExtendedAEPlus::onServerStopped);
// 注册配置接入自定义的 ModConfigs // 注册配置接入自定义的 ModConfigs
modContainer.registerConfig(ModConfig.Type.COMMON, ModConfigs.COMMON_SPEC, "extendedae_plus-common.toml"); modContainer.registerConfig(ModConfig.Type.COMMON, ModConfigs.COMMON_SPEC, "extendedae_plus-common.toml");
@ -72,17 +77,29 @@ public class ExtendedAEPlus {
} }
private static void onServerStarted(ServerStartedEvent event) { private static void onServerStarted(ServerStartedEvent event) {
serverStopping = false;
storageManagerServer = event.getServer(); storageManagerServer = event.getServer();
storageManager = InfinityStorageManager.getInstance(event.getServer()); storageManager = InfinityStorageManager.getInstance(event.getServer());
} }
private static void onServerStopping(ServerStoppingEvent event) {
serverStopping = true;
LabelNetworkRegistry.get(event.getServer()).shutdownAllVirtualNodes();
WirelessMasterRegistry.clear();
}
private static void onServerStopped(ServerStoppedEvent event) { private static void onServerStopped(ServerStoppedEvent event) {
serverStopping = false;
if (storageManagerServer == event.getServer()) { if (storageManagerServer == event.getServer()) {
storageManagerServer = null; storageManagerServer = null;
storageManager = null; storageManager = null;
} }
} }
public static boolean isServerStopping() {
return serverStopping;
}
@Nullable @Nullable
public static InfinityStorageManager currentStorageManager() { public static InfinityStorageManager currentStorageManager() {
return storageManager; return storageManager;

View File

@ -1,6 +1,7 @@
package com.extendedae_plus.ae.wireless; package com.extendedae_plus.ae.wireless;
import appeng.api.networking.GridHelper; import appeng.api.networking.GridHelper;
import appeng.api.networking.IGridConnection;
import appeng.api.networking.IGridNode; import appeng.api.networking.IGridNode;
import appeng.me.service.helpers.ConnectionWrapper; import appeng.me.service.helpers.ConnectionWrapper;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
@ -88,14 +89,62 @@ public class LabelLink {
} }
public void onUnloadOrRemove() { public void onUnloadOrRemove() {
this.target = null;
destroyConnection(); destroyConnection();
} }
private void destroyConnection() { private void destroyConnection() {
var current = connection.getConnection(); var current = connection.getConnection();
if (current != null) { if (current != null) {
var a = current.a();
var b = current.b();
current.destroy(); current.destroy();
try {
if (a != null && a.getGrid() != null) {
a.getGrid().getTickManager().wakeDevice(a);
}
} catch (Throwable ignored) {}
try {
if (b != null && b.getGrid() != null) {
b.getGrid().getTickManager().wakeDevice(b);
}
} catch (Throwable ignored) {}
connection.setConnection(null); connection.setConnection(null);
} else {
try {
IGridNode hostNode = this.host.getGridNode();
IGridNode targetNode = this.target == null ? null : this.target.node();
if (hostNode != null && targetNode != null) {
IGridConnection existing = this.findExistingConnection(hostNode, targetNode);
if (existing != null) {
existing.destroy();
try {
if (hostNode.getGrid() != null) {
hostNode.getGrid().getTickManager().wakeDevice(hostNode);
}
} catch (Throwable ignored) {}
try {
if (targetNode.getGrid() != null) {
targetNode.getGrid().getTickManager().wakeDevice(targetNode);
}
} catch (Throwable ignored) {}
}
}
} catch (Throwable ignored) {}
} }
} }
@Nullable
private IGridConnection findExistingConnection(IGridNode a, IGridNode b) {
try {
for (IGridConnection gc : a.getConnections()) {
var ga = gc.a();
var gb = gc.b();
if ((ga == a || gb == a) && (ga == b || gb == b)) {
return gc;
}
}
} catch (Throwable ignored) {}
return null;
}
} }

View File

@ -111,10 +111,19 @@ public class LabelNetworkRegistry extends SavedData {
BlockPos pos = endpoint.getBlockPos(); BlockPos pos = endpoint.getBlockPos();
for (LabelNetwork net : networks.values()) { for (LabelNetwork net : networks.values()) {
net.endpoints.removeIf(ref -> ref.matches(dimKey, pos)); net.endpoints.removeIf(ref -> ref.matches(dimKey, pos));
if (net.endpoints.isEmpty()) {
net.destroyVirtualNode();
}
} }
setDirty(); setDirty();
} }
public synchronized void shutdownAllVirtualNodes() {
for (LabelNetwork net : networks.values()) {
net.destroyVirtualNode();
}
}
public synchronized LabelNetwork getNetwork(ServerLevel level, String rawLabel, @Nullable UUID placerId) { public synchronized LabelNetwork getNetwork(ServerLevel level, String rawLabel, @Nullable UUID placerId) {
String label = normalizeLabel(rawLabel); String label = normalizeLabel(rawLabel);
if (label == null) return null; if (label == null) return null;

View File

@ -85,6 +85,10 @@ public final class WirelessMasterRegistry {
return ref == null ? null : ref.get(); return ref == null ? null : ref.get();
} }
public static synchronized void clear() {
MASTERS.clear();
}
private static void cleanupIfCleared(Key key) { private static void cleanupIfCleared(Key key) {
var ref = MASTERS.get(key); var ref = MASTERS.get(key);
if (ref != null && ref.get() == null) { if (ref != null && ref.get() == null) {

View File

@ -8,6 +8,7 @@ import appeng.api.networking.IInWorldGridNodeHost;
import appeng.api.networking.IManagedGridNode; import appeng.api.networking.IManagedGridNode;
import appeng.api.util.AECableType; import appeng.api.util.AECableType;
import appeng.blockentity.AEBaseBlockEntity; import appeng.blockentity.AEBaseBlockEntity;
import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.ae.wireless.IWirelessEndpoint; import com.extendedae_plus.ae.wireless.IWirelessEndpoint;
import com.extendedae_plus.ae.wireless.LabelLink; import com.extendedae_plus.ae.wireless.LabelLink;
import com.extendedae_plus.ae.wireless.LabelNetworkRegistry; import com.extendedae_plus.ae.wireless.LabelNetworkRegistry;
@ -194,25 +195,49 @@ public class LabeledWirelessTransceiverBlockEntity extends AEBaseBlockEntity imp
} }
public void onRemoved() { public void onRemoved() {
cleanupForRemoval();
}
@Override
public void onChunkUnloaded() {
cleanupForRemoval();
super.onChunkUnloaded();
}
@Override
public void setRemoved() {
cleanupForRemoval();
super.setRemoved();
}
private void cleanupForRemoval() {
if (this.beingRemoved) {
return;
}
this.beingRemoved = true; this.beingRemoved = true;
labelLink.onUnloadOrRemove(); this.labelLink.onUnloadOrRemove();
ServerLevel sl = getServerLevel(); ServerLevel sl = getServerLevel();
if (sl != null) { if (sl != null) {
LabelNetworkRegistry.get(sl).unregister(this); LabelNetworkRegistry.get(sl).unregister(this);
} }
if (managedNode != null) {
managedNode.destroy(); if (this.managedNode != null) {
this.managedNode.destroy();
} }
} }
public static void serverTick(Level level, BlockPos pos, BlockState state, LabeledWirelessTransceiverBlockEntity be) { public static void serverTick(Level level, BlockPos pos, BlockState state, LabeledWirelessTransceiverBlockEntity be) {
if (!(level instanceof ServerLevel)) return; if (!(level instanceof ServerLevel)) return;
if (ExtendedAEPlus.isServerStopping()) return;
be.labelLink.updateStatus(); be.labelLink.updateStatus();
be.updateState(); be.updateState();
} }
private void updateState() { private void updateState() {
if (this.level == null || this.level.isClientSide) return; if (this.level == null || this.level.isClientSide) return;
if (ExtendedAEPlus.isServerStopping()) return;
if (this.beingRemoved || this.isRemoved()) return; if (this.beingRemoved || this.isRemoved()) return;
BlockState currentState = this.getBlockState(); BlockState currentState = this.getBlockState();
if (!(currentState.getBlock() instanceof LabeledWirelessTransceiverBlock)) { if (!(currentState.getBlock() instanceof LabeledWirelessTransceiverBlock)) {
@ -307,15 +332,12 @@ public class LabeledWirelessTransceiverBlockEntity extends AEBaseBlockEntity imp
} }
@Override @Override
public void onStateChanged(LabeledWirelessTransceiverBlockEntity host, IGridNode node, State state) { public void onStateChanged(LabeledWirelessTransceiverBlockEntity host, IGridNode node, State state) {
host.updateState();
} }
@Override @Override
public void onInWorldConnectionChanged(LabeledWirelessTransceiverBlockEntity host, IGridNode node) { public void onInWorldConnectionChanged(LabeledWirelessTransceiverBlockEntity host, IGridNode node) {
host.updateState();
} }
@Override @Override
public void onGridChanged(LabeledWirelessTransceiverBlockEntity host, IGridNode node) { public void onGridChanged(LabeledWirelessTransceiverBlockEntity host, IGridNode node) {
host.updateState();
} }
@Override @Override
public void onOwnerChanged(LabeledWirelessTransceiverBlockEntity host, IGridNode node) {} public void onOwnerChanged(LabeledWirelessTransceiverBlockEntity host, IGridNode node) {}

View File

@ -42,6 +42,8 @@ public class WirelessTransceiverBlockEntity extends AEBaseBlockEntity implements
@Nullable @Nullable
private String placerName; // 放置者名称用于显示 private String placerName; // 放置者名称用于显示
private boolean beingRemoved = false;
private WirelessMasterLink masterLink; private WirelessMasterLink masterLink;
private WirelessSlaveLink slaveLink; private WirelessSlaveLink slaveLink;
@ -247,11 +249,33 @@ public class WirelessTransceiverBlockEntity extends AEBaseBlockEntity implements
} }
void onRemoved() { void onRemoved() {
cleanupForRemoval();
}
@Override
public void onChunkUnloaded() {
cleanupForRemoval();
super.onChunkUnloaded();
}
@Override
public void setRemoved() {
cleanupForRemoval();
super.setRemoved();
}
private void cleanupForRemoval() {
if (this.beingRemoved) {
return;
}
this.beingRemoved = true;
if (this.masterMode) { if (this.masterMode) {
this.masterLink.onUnloadOrRemove(); this.masterLink.onUnloadOrRemove();
} else { } else {
this.slaveLink.onUnloadOrRemove(); this.slaveLink.onUnloadOrRemove();
} }
if (this.managedNode != null) { if (this.managedNode != null) {
this.managedNode.destroy(); this.managedNode.destroy();
} }