实体加速器适配频道卡

This commit is contained in:
GaLi 2025-11-25 15:02:35 +08:00
parent 80b2194a85
commit 61c9ce6606
2 changed files with 173 additions and 6 deletions

View File

@ -5,6 +5,7 @@ import appeng.api.config.PowerMultiplier;
import appeng.api.config.YesNo; import appeng.api.config.YesNo;
import appeng.api.networking.GridFlags; import appeng.api.networking.GridFlags;
import appeng.api.networking.IGridNode; import appeng.api.networking.IGridNode;
import appeng.api.networking.IGridNodeListener;
import appeng.api.networking.energy.IEnergyService; import appeng.api.networking.energy.IEnergyService;
import appeng.api.networking.security.IActionSource; import appeng.api.networking.security.IActionSource;
import appeng.api.networking.ticking.IGridTickable; import appeng.api.networking.ticking.IGridTickable;
@ -12,8 +13,10 @@ import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.networking.ticking.TickingRequest; import appeng.api.networking.ticking.TickingRequest;
import appeng.api.parts.IPartCollisionHelper; import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartItem; import appeng.api.parts.IPartItem;
import appeng.api.parts.IPartModel; import appeng.api.parts.IPartModel;
import appeng.api.storage.MEStorage; import appeng.api.storage.MEStorage;
import appeng.api.upgrades.IUpgradeInventory;
import appeng.api.upgrades.IUpgradeableObject; import appeng.api.upgrades.IUpgradeableObject;
import appeng.core.definitions.AEItems; import appeng.core.definitions.AEItems;
import appeng.items.parts.PartModels; import appeng.items.parts.PartModels;
@ -23,16 +26,22 @@ import appeng.parts.PartModel;
import appeng.parts.automation.UpgradeablePart; import appeng.parts.automation.UpgradeablePart;
import com.extendedae_plus.ExtendedAEPlus; import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.ae.menu.EntitySpeedTickerMenu; import com.extendedae_plus.ae.menu.EntitySpeedTickerMenu;
import com.extendedae_plus.ae.wireless.WirelessSlaveLink;
import com.extendedae_plus.ae.wireless.endpoint.GenericNodeEndpointImpl;
import com.extendedae_plus.api.bridge.IInterfaceWirelessLinkBridge;
import com.extendedae_plus.api.config.Settings; import com.extendedae_plus.api.config.Settings;
import com.extendedae_plus.config.ModConfig; import com.extendedae_plus.config.ModConfig;
import com.extendedae_plus.init.ModItems; import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.init.ModMenuTypes; import com.extendedae_plus.init.ModMenuTypes;
import com.extendedae_plus.items.materials.ChannelCardItem;
import com.extendedae_plus.util.Logger; import com.extendedae_plus.util.Logger;
import com.extendedae_plus.util.ModCheckUtils; import com.extendedae_plus.util.ModCheckUtils;
import com.extendedae_plus.util.entitySpeed.ConfigParsingUtils; import com.extendedae_plus.util.entitySpeed.ConfigParsingUtils;
import com.extendedae_plus.util.entitySpeed.PowerUtils; import com.extendedae_plus.util.entitySpeed.PowerUtils;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.MenuProvider; import net.minecraft.world.MenuProvider;
@ -51,12 +60,16 @@ import org.jetbrains.annotations.Nullable;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Objects;
import java.util.UUID;
/** /**
* 实体加速器部件用于加速目标方块实体的 tick 速率消耗 AE 网络能量支持加速卡和能量卡升级 * 实体加速器部件用于加速目标方块实体的 tick 速率消耗 AE 网络能量支持加速卡和能量卡升级
* 灵感来源于 <a href="https://github.com/GilbertzRivi/crazyae2addons">Crazy AE2 Addons</a> * 灵感来源于 <a href="https://github.com/GilbertzRivi/crazyae2addons">Crazy AE2 Addons</a>
*/ */
public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTickable, MenuProvider, IUpgradeableObject { public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTickable, MenuProvider, IUpgradeableObject,
IInterfaceWirelessLinkBridge {
public static final ResourceLocation MODEL_BASE = new ResourceLocation(ExtendedAEPlus.MODID, "part/entity_speed_ticker_part"); public static final ResourceLocation MODEL_BASE = new ResourceLocation(ExtendedAEPlus.MODID, "part/entity_speed_ticker_part");
@PartModels @PartModels
@ -92,6 +105,11 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
private int cachedEnergyCardCount = -1; // 缓存的能量卡数量 private int cachedEnergyCardCount = -1; // 缓存的能量卡数量
private BlockEntity cachedTarget = null; private BlockEntity cachedTarget = null;
private BlockPos cachedTargetPos = null; private BlockPos cachedTargetPos = null;
private WirelessSlaveLink wirelessLink;
private long lastChannelFrequency = -1L;
private UUID lastChannelOwner;
private boolean wirelessClientConnected = false;
private boolean wirelessPendingInit = true;
/** /**
* 构造函数初始化部件并设置网络节点属性 * 构造函数初始化部件并设置网络节点属性
@ -227,13 +245,16 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
if (menu != null) { if (menu != null) {
menu.broadcastChanges(); menu.broadcastChanges();
} }
scheduleWirelessInit();
} }
@Override @Override
public void onNeighborChanged(BlockGetter level, BlockPos pos, BlockPos neighbor) { protected void onMainNodeStateChanged(IGridNodeListener.State reason) {
super.onNeighborChanged(level, pos, neighbor); super.onMainNodeStateChanged(reason);
// 当邻居方块变化时更新红石状态 if (reason == IGridNodeListener.State.GRID_BOOT) {
updateRedstoneState(); scheduleWirelessInit();
}
} }
/** /**
@ -245,6 +266,8 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
*/ */
@Override @Override
public TickRateModulation tickingRequest(IGridNode iGridNode, int ticksSinceLastCall) { public TickRateModulation tickingRequest(IGridNode iGridNode, int ticksSinceLastCall) {
handleWirelessLogic();
if (!getAccelerateEnabled()) { if (!getAccelerateEnabled()) {
return TickRateModulation.IDLE; return TickRateModulation.IDLE;
} }
@ -489,6 +512,10 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
super.removeFromWorld(); super.removeFromWorld();
cachedTarget = null; cachedTarget = null;
cachedTargetPos = null; cachedTargetPos = null;
if (wirelessLink != null) {
wirelessLink.onUnloadOrRemove();
wirelessLink = null;
}
} }
// 获取红石信号状态 // 获取红石信号状态
@ -507,4 +534,143 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
: YesNo.NO; : YesNo.NO;
} }
} }
private void handleWirelessLogic() {
if (!isServerEnvironmentReady()) {
return;
}
if (wirelessPendingInit) {
initializeWirelessLink();
} else {
eap$updateWirelessLink();
}
}
private boolean isServerEnvironmentReady() {
var be = getBlockEntity();
return be != null && be.getLevel() != null && !be.getLevel().isClientSide();
}
private void scheduleWirelessInit() {
wirelessPendingInit = true;
}
private void resetWirelessState() {
lastChannelFrequency = -1L;
lastChannelOwner = null;
scheduleWirelessInit();
}
private void initializeWirelessLink() {
if (!isServerEnvironmentReady()) {
return;
}
wirelessPendingInit = false;
try {
IUpgradeInventory upgrades = this.getUpgrades();
long channel = 0L;
UUID ownerUUID = null;
boolean found = false;
for (var stack : upgrades) {
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
channel = ChannelCardItem.getChannel(stack);
ownerUUID = ChannelCardItem.getOwnerUUID(stack);
found = true;
break;
}
}
if (!found) {
disconnectWirelessLink();
return;
}
if (wirelessLink == null) {
var endpoint = new GenericNodeEndpointImpl(
() -> {
var host = this.getHost();
return host != null ? host.getBlockEntity() : null;
},
this::getActionableNode
);
wirelessLink = new WirelessSlaveLink(endpoint);
Logger.EAP$LOGGER.debug("[服务端] EntitySpeedTicker 创建无线链接");
}
boolean changed = lastChannelFrequency != channel || !Objects.equals(lastChannelOwner, ownerUUID);
wirelessLink.setPlacerId(ownerUUID);
wirelessLink.setFrequency(channel);
wirelessLink.updateStatus();
lastChannelFrequency = channel;
lastChannelOwner = ownerUUID;
if (changed) {
markPartForUpdate();
Logger.EAP$LOGGER.debug("[服务端] EntitySpeedTicker 设置频道: {}, connected={}",
channel, wirelessLink.isConnected());
}
} catch (Exception e) {
Logger.EAP$LOGGER.error("[服务端] EntitySpeedTicker 初始化频道链接失败", e);
}
}
private void disconnectWirelessLink() {
lastChannelFrequency = 0L;
lastChannelOwner = null;
if (wirelessLink != null) {
wirelessLink.setFrequency(0L);
wirelessLink.updateStatus();
}
markPartForUpdate();
}
private void markPartForUpdate() {
var host = this.getHost();
if (host != null) {
host.markForUpdate();
}
}
@Override
public void eap$updateWirelessLink() {
if (wirelessLink != null && isServerEnvironmentReady()) {
wirelessLink.updateStatus();
}
}
@Override
public boolean eap$isWirelessConnected() {
if (this.isClientSide()) {
return wirelessClientConnected;
}
return wirelessLink != null && wirelessLink.isConnected();
}
@Override
public void eap$setClientWirelessState(boolean connected) {
this.wirelessClientConnected = connected;
}
@Override
public boolean eap$hasTickInitialized() {
return !wirelessPendingInit;
}
@Override
public void eap$setTickInitialized(boolean initialized) {
this.wirelessPendingInit = !initialized;
}
@Override
public void eap$initializeChannelLink() {
scheduleWirelessInit();
}
@Override
public void eap$handleDelayedInit() {
handleWirelessLogic();
}
} }

View File

@ -15,10 +15,11 @@ import static com.glodblock.github.extendedae.common.EPPItemAndBlock.*;
public final class UpgradeCards { public final class UpgradeCards {
public UpgradeCards(final FMLCommonSetupEvent event) { public UpgradeCards(final FMLCommonSetupEvent event) {
event.enqueueWork(() -> { event.enqueueWork(() -> {
// 现有 Entity Ticker 的部件注册为处理 SPEED/ENERGY 卡的宿主 // 现有 Entity Ticker 的部件注册为处理 SPEED/ENERGY/CHANNEL 卡的宿主
Upgrades.add(AEItems.ENERGY_CARD, ModItems.ENTITY_TICKER_PART_ITEM.get(), 8, "group.entity_ticker.name"); Upgrades.add(AEItems.ENERGY_CARD, ModItems.ENTITY_TICKER_PART_ITEM.get(), 8, "group.entity_ticker.name");
// 使用单一的 UpgradeCard Item 作为注册键总共允许安装 4 不同等级由 ItemStack NBT 区分 // 使用单一的 UpgradeCard Item 作为注册键总共允许安装 4 不同等级由 ItemStack NBT 区分
Upgrades.add(ModItems.ENTITY_SPEED_CARD.get(), ModItems.ENTITY_TICKER_PART_ITEM.get(), 4, "group.entity_ticker.name"); Upgrades.add(ModItems.ENTITY_SPEED_CARD.get(), ModItems.ENTITY_TICKER_PART_ITEM.get(), 4, "group.entity_ticker.name");
Upgrades.add(ModItems.CHANNEL_CARD.get(), ModItems.ENTITY_TICKER_PART_ITEM.get(), 1, "group.entity_ticker.name");
// 新增频道卡仅允许安装在 ME 接口方块与部件每台最多 1 // 新增频道卡仅允许安装在 ME 接口方块与部件每台最多 1
String interfaceGroup = GuiText.Interface.getTranslationKey(); String interfaceGroup = GuiText.Interface.getTranslationKey();