频道卡

This commit is contained in:
GaLicn 2025-09-24 13:04:46 +08:00
parent 47aa90a438
commit 0571efe2f9
14 changed files with 758 additions and 0 deletions

View File

@ -0,0 +1,66 @@
package com.extendedae_plus.ae.items;
import appeng.items.materials.UpgradeCardItem;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* 频道卡MVP仅存储一个 long 类型的频道号到 NBT"channel"
* 继承 AE2 UpgradeCardItem 以复用升级卡判定与提示框架
*/
public class ChannelCardItem extends UpgradeCardItem {
public static final String TAG_CHANNEL = "channel";
public ChannelCardItem(Item.Properties properties) {
super(properties);
}
public static void setChannel(ItemStack stack, long channel) {
CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
tag.putLong(TAG_CHANNEL, channel);
stack.set(DataComponents.CUSTOM_DATA, CustomData.of(tag));
}
public static long getChannel(ItemStack stack) {
CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
return tag.contains(TAG_CHANNEL) ? tag.getLong(TAG_CHANNEL) : 0L;
}
@Override
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> lines, TooltipFlag flag) {
super.appendHoverText(stack, context, lines, flag);
long ch = getChannel(stack);
if (ch == 0L) {
lines.add(Component.translatable("item.extendedae_plus.channel_card.channel.unset"));
} else {
lines.add(Component.translatable("item.extendedae_plus.channel_card.channel", ch));
}
}
@Override
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
ItemStack stack = player.getItemInHand(hand);
if (!level.isClientSide) {
long ch = getChannel(stack);
boolean dec = player.isShiftKeyDown();
long next = dec ? Math.max(0L, ch - 1L) : ch + 1L;
if (next != ch) {
setChannel(stack, next);
player.displayClientMessage(Component.translatable("item.extendedae_plus.channel_card.set", next), true);
}
}
return InteractionResultHolder.sidedSuccess(stack, level.isClientSide);
}
}

View File

@ -0,0 +1,50 @@
package com.extendedae_plus.bridge;
/**
* mixin 包下的桥接接口 mixin 进行 instanceof 检测和回调
*/
public interface InterfaceWirelessLinkBridge {
void eap$updateWirelessLink();
/**
* 获取无线连接状态服务端返回真实状态客户端返回同步状态
*/
default boolean eap$isWirelessConnected() {
return false;
}
/**
* 设置客户端的无线连接状态仅在客户端使用
*/
default void eap$setClientWirelessState(boolean connected) {
// 默认实现为空
}
/**
* 检查是否已经进行过tick初始化
*/
default boolean eap$hasTickInitialized() {
return true; // 默认认为已初始化
}
/**
* 设置tick初始化状态
*/
default void eap$setTickInitialized(boolean initialized) {
// 默认实现为空
}
/**
* 执行频道链接初始化
*/
default void eap$initializeChannelLink() {
// 默认实现为空
}
/**
* 检查并处理延迟初始化
*/
default void eap$handleDelayedInit() {
// 默认实现为空
}
}

View File

@ -24,6 +24,7 @@ public final class ModCreativeTabs {
output.accept(ModItems.ACCELERATOR_256x.get());
output.accept(ModItems.ACCELERATOR_1024x.get());
output.accept(ModItems.ASSEMBLER_MATRIX_UPLOAD_CORE.get());
output.accept(ModItems.CHANNEL_CARD.get());
output.accept(ModItems.ENTITY_TICKER_PART_ITEM.get());
// 放入四个预设的 stacksx2,x4,x8,x16使用 ModItems 工厂创建
output.accept(ModItems.createEntitySpeedCardStack((byte) 2));

View File

@ -3,6 +3,7 @@ package com.extendedae_plus.init;
import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.ae.definitions.upgrades.EntitySpeedCardItem;
import com.extendedae_plus.ae.items.EntitySpeedTickerPartItem;
import com.extendedae_plus.ae.items.ChannelCardItem;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
@ -62,6 +63,12 @@ public final class ModItems {
() -> new EntitySpeedCardItem(new Item.Properties())
);
// 频道卡用于AE机器的无线频道连接
public static final DeferredItem<ChannelCardItem> CHANNEL_CARD = ITEMS.register(
"channel_card",
() -> new ChannelCardItem(new Item.Properties())
);
/**
* 工厂创建带 multiplier 的实体加速卡 ItemStack2/4/8/16
*/

View File

@ -0,0 +1,225 @@
package com.extendedae_plus.mixin.ae2.helpers;
import appeng.api.upgrades.IUpgradeInventory;
import appeng.helpers.InterfaceLogic;
import appeng.helpers.InterfaceLogicHost;
import com.extendedae_plus.ae.items.ChannelCardItem;
import com.extendedae_plus.bridge.InterfaceWirelessLinkBridge;
import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.wireless.WirelessSlaveLink;
import com.extendedae_plus.wireless.endpoint.InterfaceNodeEndpointImpl;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
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;
@Mixin(InterfaceLogic.class)
public abstract class InterfaceLogicChannelCardMixin implements InterfaceWirelessLinkBridge {
@Shadow(remap = false) public abstract IUpgradeInventory getUpgrades();
@Shadow(remap = false) public abstract appeng.api.networking.IGridNode getActionableNode();
@Shadow(remap = false) protected InterfaceLogicHost host;
@Shadow(remap = false) protected appeng.api.networking.IManagedGridNode mainNode;
@Unique
private WirelessSlaveLink eap$link;
@Unique
private long eap$lastChannel = -1;
@Unique
private boolean eap$clientConnected = false;
@Unique
private boolean eap$hasInitialized = false;
@Unique
private int eap$delayedInitTicks = 0;
static {
// InterfaceLogicChannelCardMixin 已加载
}
@Inject(method = "onUpgradesChanged", at = @At("TAIL"), remap = false)
private void eap$onUpgradesChangedTail(CallbackInfo ci) {
// 升级变更时重置标志并尝试初始化
eap$lastChannel = -1;
eap$hasInitialized = false;
eap$initializeChannelLink();
}
@Inject(method = "gridChanged", at = @At("TAIL"), remap = false)
private void eap$afterGridChanged(CallbackInfo ci) {
// 网格状态变化时重置标志并设置延迟初始化
eap$lastChannel = -1;
eap$hasInitialized = false;
eap$delayedInitTicks = 10; // 适当增加延迟tick等待网格完成引导
// 尝试唤醒设备确保后续还能继续tick
if (mainNode != null) {
mainNode.ifPresent((grid, node) -> {
try {
grid.getTickManager().wakeDevice(node);
} catch (Throwable ignored) {
}
});
}
}
@Inject(method = "readFromNBT", at = @At("TAIL"), remap = false)
private void eap$afterReadNBT(net.minecraft.nbt.CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) {
// NBT加载时重置标志
eap$lastChannel = -1;
eap$hasInitialized = false;
// 直接尝试初始化
eap$initializeChannelLink();
}
@Inject(method = "clearContent", at = @At("HEAD"), remap = false)
private void eap$onClearContent(CallbackInfo ci) {
if (eap$link != null) {
eap$link.onUnloadOrRemove();
}
}
@Unique
public void eap$initializeChannelLink() {
// 仅在服务端执行避免在渲染线程/客户端触发任何初始化路径
if (host.getBlockEntity() != null && host.getBlockEntity().getLevel() != null && host.getBlockEntity().getLevel().isClientSide) {
return;
}
// 避免重复初始化
if (eap$hasInitialized) {
return;
}
// 检查网格节点是否在线1.21.1版本使用isActive替代hasGridBooted
if (mainNode == null || !mainNode.isActive()) {
return;
}
try {
long channel = 0L;
boolean found = false;
for (ItemStack stack : getUpgrades()) {
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
channel = ChannelCardItem.getChannel(stack);
found = true;
break;
}
}
if (!found) {
// 无频道卡断开并视为初始化完成
if (eap$link != null) {
eap$link.setFrequency(0L);
eap$link.updateStatus();
}
eap$hasInitialized = true;
return;
}
if (eap$link == null) {
var endpoint = new InterfaceNodeEndpointImpl(host, () -> this.mainNode.getNode());
eap$link = new WirelessSlaveLink(endpoint);
}
eap$link.setFrequency(channel);
eap$link.updateStatus();
if (eap$link.isConnected()) {
eap$hasInitialized = true; // 设置初始化完成标志
} else {
// 不标记为完成允许后续tick重试
eap$hasInitialized = false;
// 设置一个短延迟窗口避免每tick刷屏
eap$delayedInitTicks = Math.max(eap$delayedInitTicks, 5);
try {
mainNode.ifPresent((grid, node) -> {
try {
grid.getTickManager().wakeDevice(node);
} catch (Throwable ignored) {
}
});
} catch (Throwable ignored) {
}
}
} catch (Exception ignored) {
}
}
@Override
public void eap$updateWirelessLink() {
if (eap$link != null) {
eap$link.updateStatus();
}
}
@Override
public boolean eap$isWirelessConnected() {
// InterfaceLogic没有isClientSide方法需要通过host判断
if (host.getBlockEntity() != null && host.getBlockEntity().getLevel() != null && host.getBlockEntity().getLevel().isClientSide) {
return eap$clientConnected;
} else {
return eap$link != null && eap$link.isConnected();
}
}
@Override
public void eap$setClientWirelessState(boolean connected) {
eap$clientConnected = connected;
}
@Override
public boolean eap$hasTickInitialized() {
return eap$hasInitialized;
}
@Override
public void eap$setTickInitialized(boolean initialized) {
eap$hasInitialized = initialized;
}
@Override
public void eap$handleDelayedInit() {
// 仅在服务端执行延迟初始化避免在渲染线程/客户端触发任何初始化路径
if (host.getBlockEntity() != null && host.getBlockEntity().getLevel() != null && host.getBlockEntity().getLevel().isClientSide) {
return;
}
// 若尚未初始化则持续尝试直到网格完成引导
if (!eap$hasInitialized) {
if (mainNode == null || !mainNode.isActive()) {
// 仍在引导消耗计时器
if (eap$delayedInitTicks > 0) {
eap$delayedInitTicks--;
}
if (eap$delayedInitTicks == 0) {
// 重新设定一个短延迟窗口并唤醒设备以保证后续还能继续 tick
eap$delayedInitTicks = 5;
try {
mainNode.ifPresent((grid, node) -> {
try {
grid.getTickManager().wakeDevice(node);
} catch (Throwable ignored) {
}
});
} catch (Throwable ignored) {
}
}
} else {
// 网格已引导完成执行初始化
eap$initializeChannelLink();
}
}
}
// eap$initializeChannelLink方法已在上面实现
}

View File

@ -0,0 +1,145 @@
package com.extendedae_plus.mixin.ae2.parts.automation;
import appeng.api.networking.security.IActionHost;
import appeng.api.upgrades.IUpgradeInventory;
import appeng.api.upgrades.IUpgradeableObject;
import appeng.helpers.InterfaceLogicHost;
import appeng.parts.automation.IOBusPart;
import net.minecraft.nbt.CompoundTag;
import com.extendedae_plus.util.ExtendedAELogger;
import com.extendedae_plus.ae.items.ChannelCardItem;
import com.extendedae_plus.bridge.InterfaceWirelessLinkBridge;
import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.wireless.WirelessSlaveLink;
import com.extendedae_plus.wireless.endpoint.GenericNodeEndpointImpl;
import net.minecraft.network.FriendlyByteBuf;
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;
/**
* AE2 I/O 总线注入频道卡联动在升级变更时读取频道并更新无线链接
*/
@Mixin(value = IOBusPart.class, remap = false)
public abstract class IOBusPartChannelCardMixin implements InterfaceWirelessLinkBridge, IUpgradeableObject {
@Unique
private WirelessSlaveLink eap$link;
@Unique
private long eap$lastChannel = -1;
@Unique
private boolean eap$clientConnected = false;
@Unique
private boolean eap$hasTickInitialized = false;
@Inject(method = "upgradesChanged", at = @At("TAIL"))
private void eap$onUpgradesChanged(CallbackInfo ci) {
// 只在服务端初始化频道链接
if (!((appeng.parts.AEBasePart)(Object)this).isClientSide()) {
eap$initializeChannelLink();
}
}
@Inject(method = "tickingRequest", at = @At("HEAD"))
private void eap$beforeTick(appeng.api.networking.IGridNode node, int ticksSinceLastCall, org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable<appeng.api.networking.ticking.TickRateModulation> cir) {
// 在第一次tick时初始化频道链接此时网格节点已经在线
if (!eap$hasTickInitialized && !((appeng.parts.AEBasePart)(Object)this).isClientSide()) {
eap$hasTickInitialized = true;
eap$initializeChannelLink();
}
}
@Inject(method = "readFromNBT", at = @At("TAIL"))
private void eap$afterReadFromNBT(CompoundTag extra, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) {
// 从NBT加载时重置频道缓存和tick初始化标志
if (!((appeng.parts.AEBasePart)(Object)this).isClientSide()) {
eap$lastChannel = -1;
eap$hasTickInitialized = false; // 重置标志允许再次初始化
}
}
@Unique
public void eap$initializeChannelLink() {
// 防止重复调用
if (((appeng.parts.AEBasePart)(Object)this).isClientSide()) {
return;
}
try {
IUpgradeInventory inv = this.getUpgrades();
long channel = 0L;
boolean found = false;
for (var stack : inv) {
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
channel = ChannelCardItem.getChannel(stack);
found = true;
break;
}
}
// 频道没有变化则跳过
if (eap$lastChannel == channel) {
return;
}
eap$lastChannel = channel;
ExtendedAELogger.LOGGER.debug("[服务端] IOBus 初始化频道链接: found={}, channel={}", found, channel);
if (!found) {
// 无频道卡则断开
if (eap$link != null) {
eap$link.setFrequency(0L);
eap$link.updateStatus();
ExtendedAELogger.LOGGER.debug("[服务端] IOBus 断开频道链接");
// 立即通知客户端状态变化断开连接无需延迟
((appeng.parts.AEBasePart)(Object)this).getHost().markForUpdate();
}
return;
}
if (eap$link == null) {
var endpoint = new GenericNodeEndpointImpl(
() -> ((appeng.parts.AEBasePart)(Object)this).getHost().getBlockEntity(),
() -> ((IActionHost)(Object)this).getActionableNode()
);
eap$link = new WirelessSlaveLink(endpoint);
ExtendedAELogger.LOGGER.debug("[服务端] IOBus 创建新的无线链接");
}
eap$link.setFrequency(channel);
eap$link.updateStatus();
ExtendedAELogger.LOGGER.debug("[服务端] IOBus 设置频道: {}, 连接状态: {}", channel, eap$link.isConnected());
// 通知客户端状态变化
((appeng.parts.AEBasePart)(Object)this).getHost().markForUpdate();
} catch (Exception e) {
ExtendedAELogger.LOGGER.error("[服务端] IOBus 初始化频道链接失败", e);
}
}
@Override
public void eap$updateWirelessLink() {
if (eap$link != null) {
eap$link.updateStatus();
}
}
@Override
public boolean eap$isWirelessConnected() {
if (((appeng.parts.AEBasePart)(Object)this).isClientSide()) {
return eap$clientConnected;
} else {
return eap$link != null && eap$link.isConnected();
}
}
@Override
public void eap$setClientWirelessState(boolean connected) {
eap$clientConnected = connected;
}
}

View File

@ -0,0 +1,141 @@
package com.extendedae_plus.mixin.ae2.parts.storagebus;
import appeng.api.networking.IGridNodeListener;
import appeng.api.networking.security.IActionHost;
import appeng.api.upgrades.IUpgradeInventory;
import appeng.api.upgrades.IUpgradeableObject;
import appeng.parts.storagebus.StorageBusPart;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import com.extendedae_plus.util.ExtendedAELogger;
import com.extendedae_plus.ae.items.ChannelCardItem;
import com.extendedae_plus.bridge.InterfaceWirelessLinkBridge;
import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.wireless.WirelessSlaveLink;
import com.extendedae_plus.wireless.endpoint.GenericNodeEndpointImpl;
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;
/**
* AE2 的存储总线注入频道卡联动在升级变更时读取频道并更新无线链接
*/
@Mixin(value = StorageBusPart.class, remap = false)
public abstract class StorageBusPartChannelCardMixin implements InterfaceWirelessLinkBridge, IUpgradeableObject {
@Unique
private WirelessSlaveLink eap$link;
@Unique
private long eap$lastChannel = -1;
@Unique
private boolean eap$clientConnected = false;
@Inject(method = "upgradesChanged", at = @At("TAIL"))
private void eap$onUpgradesChanged(CallbackInfo ci) {
// 只在服务端初始化频道链接
if (!((appeng.parts.AEBasePart)(Object)this).isClientSide()) {
eap$initializeChannelLink();
}
}
@Inject(method = "onMainNodeStateChanged", at = @At("TAIL"))
private void eap$onMainNodeStateChanged(IGridNodeListener.State reason, CallbackInfo ci) {
// 在节点状态变化时包括加载后的GRID_BOOT重新初始化频道链接
if (reason == IGridNodeListener.State.GRID_BOOT && !((appeng.parts.AEBasePart)(Object)this).isClientSide()) {
eap$initializeChannelLink();
}
}
@Inject(method = "readFromNBT", at = @At("TAIL"))
private void eap$afterReadFromNBT(CompoundTag extra, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) {
// 从NBT加载后也重新初始化频道链接只在服务端
if (!((appeng.parts.AEBasePart)(Object)this).isClientSide()) {
// 从NBT加载时重置频道缓存强制重新初始化
eap$lastChannel = -1;
eap$initializeChannelLink();
}
}
@Unique
public void eap$initializeChannelLink() {
// 防止重复调用
if (((appeng.parts.AEBasePart)(Object)this).isClientSide()) {
return;
}
try {
IUpgradeInventory inv = this.getUpgrades();
long channel = 0L;
boolean found = false;
for (var stack : inv) {
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
channel = ChannelCardItem.getChannel(stack);
found = true;
break;
}
}
// 频道没有变化则跳过
if (eap$lastChannel == channel) {
return;
}
eap$lastChannel = channel;
ExtendedAELogger.LOGGER.debug("[服务端] StorageBus 初始化频道链接: found={}, channel={}", found, channel);
if (!found) {
if (eap$link != null) {
eap$link.setFrequency(0L);
eap$link.updateStatus();
ExtendedAELogger.LOGGER.debug("[服务端] StorageBus 断开频道链接");
// 通知客户端状态变化
((appeng.parts.AEBasePart)(Object)this).getHost().markForUpdate();
}
return;
}
if (eap$link == null) {
var endpoint = new GenericNodeEndpointImpl(
() -> ((appeng.parts.AEBasePart)(Object)this).getHost().getBlockEntity(),
() -> ((IActionHost)(Object)this).getActionableNode()
);
eap$link = new WirelessSlaveLink(endpoint);
ExtendedAELogger.LOGGER.debug("[服务端] StorageBus 创建新的无线链接");
}
eap$link.setFrequency(channel);
eap$link.updateStatus();
ExtendedAELogger.LOGGER.debug("[服务端] StorageBus 设置频道: {}, 连接状态: {}", channel, eap$link.isConnected());
// 通知客户端状态变化
((appeng.parts.AEBasePart)(Object)this).getHost().markForUpdate();
} catch (Exception e) {
ExtendedAELogger.LOGGER.error("[服务端] StorageBus 初始化频道链接失败", e);
}
}
@Override
public void eap$updateWirelessLink() {
if (eap$link != null) {
eap$link.updateStatus();
}
}
@Override
public boolean eap$isWirelessConnected() {
if (((appeng.parts.AEBasePart)(Object)this).isClientSide()) {
return eap$clientConnected;
} else {
return eap$link != null && eap$link.isConnected();
}
}
@Override
public void eap$setClientWirelessState(boolean connected) {
eap$clientConnected = connected;
}
}

View File

@ -0,0 +1,49 @@
package com.extendedae_plus.wireless.endpoint;
import appeng.api.networking.IGridNode;
import com.extendedae_plus.wireless.IWirelessEndpoint;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import java.util.Objects;
import java.util.function.Supplier;
/**
* 通用 IWirelessEndpoint通过提供方块实体与节点的 Supplier 实现
*/
public class GenericNodeEndpointImpl implements IWirelessEndpoint {
private final Supplier<BlockEntity> blockEntitySupplier;
private final Supplier<IGridNode> nodeSupplier;
public GenericNodeEndpointImpl(Supplier<BlockEntity> blockEntitySupplier, Supplier<IGridNode> nodeSupplier) {
this.blockEntitySupplier = Objects.requireNonNull(blockEntitySupplier);
this.nodeSupplier = Objects.requireNonNull(nodeSupplier);
}
@Override
public ServerLevel getServerLevel() {
var be = blockEntitySupplier.get();
if (be == null) return null;
Level lvl = be.getLevel();
return (lvl instanceof ServerLevel) ? (ServerLevel) lvl : null;
}
@Override
public BlockPos getBlockPos() {
var be = blockEntitySupplier.get();
return be != null ? be.getBlockPos() : BlockPos.ZERO;
}
@Override
public IGridNode getGridNode() {
return nodeSupplier.get();
}
@Override
public boolean isEndpointRemoved() {
var be = blockEntitySupplier.get();
return be == null || be.isRemoved();
}
}

View File

@ -0,0 +1,49 @@
package com.extendedae_plus.wireless.endpoint;
import appeng.api.networking.IGridNode;
import appeng.helpers.InterfaceLogicHost;
import com.extendedae_plus.wireless.IWirelessEndpoint;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import java.util.Objects;
import java.util.function.Supplier;
/**
* IWirelessEndpoint 实现基于 InterfaceLogicHost 与节点提供者
*/
public class InterfaceNodeEndpointImpl implements IWirelessEndpoint {
private final InterfaceLogicHost host;
private final Supplier<IGridNode> nodeSupplier;
public InterfaceNodeEndpointImpl(InterfaceLogicHost host, Supplier<IGridNode> nodeSupplier) {
this.host = Objects.requireNonNull(host);
this.nodeSupplier = Objects.requireNonNull(nodeSupplier);
}
@Override
public ServerLevel getServerLevel() {
var be = host.getBlockEntity();
if (be == null) return null;
Level lvl = be.getLevel();
return (lvl instanceof ServerLevel) ? (ServerLevel) lvl : null;
}
@Override
public BlockPos getBlockPos() {
var be = host.getBlockEntity();
return be != null ? be.getBlockPos() : BlockPos.ZERO;
}
@Override
public IGridNode getGridNode() {
return nodeSupplier.get();
}
@Override
public boolean isEndpointRemoved() {
var be = host.getBlockEntity();
return be == null || be.isRemoved();
}
}

View File

@ -18,6 +18,10 @@
"item.extendedae_plus.1024x_crafting_accelerator": "1024x Crafting Accelerator",
"item.extendedae_plus.network_pattern_controller": "Pattern Provider Status Controller",
"item.extendedae_plus.assembler_matrix_upload_core": "Assembly Matrix Upload Core",
"item.extendedae_plus.channel_card": "Channel Card",
"item.extendedae_plus.channel_card.channel": "Channel: %d",
"item.extendedae_plus.channel_card.channel.unset": "Channel: Unset",
"item.extendedae_plus.channel_card.set": "Channel set to: %d",
"item.extendedae_plus.entity_speed_card": "Entity Speed Card",
"item.extendedae_plus.entity_speed_card.x2": "Entity Speed Card (x2)",
"item.extendedae_plus.entity_speed_card.x4": "Entity Speed Card (x4)",

View File

@ -18,6 +18,10 @@
"item.extendedae_plus.1024x_crafting_accelerator": "1024x并行处理单元",
"item.extendedae_plus.network_pattern_controller": "样板供应器状态控制器",
"item.extendedae_plus.assembler_matrix_upload_core": "装配矩阵上传核心",
"item.extendedae_plus.channel_card": "频道卡",
"item.extendedae_plus.channel_card.channel": "频道: %d",
"item.extendedae_plus.channel_card.channel.unset": "频道: 未设置",
"item.extendedae_plus.channel_card.set": "频道已设置为: %d",
"item.extendedae_plus.entity_speed_card": "实体加速卡",
"item.extendedae_plus.entity_speed_card.x2": "实体加速卡 (x2)",
"item.extendedae_plus.entity_speed_card.x4": "实体加速卡 (x4)",

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "extendedae_plus:item/channel_card"
}
}

View File

@ -0,0 +1,8 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{ "item": "ae2:advanced_card" },
{ "item": "extendedae_plus:wireless_transceiver" }
],
"result": { "item": "extendedae_plus:channel_card", "count": 1 }
}

View File

@ -25,8 +25,11 @@
"ae2.autopattern.CraftingTreeNodeMixin",
"ae2.autopattern.CraftingTreeProcessMixin",
"ae2.autopattern.PatternProviderLogicContainsRedirectMixin",
"ae2.helpers.InterfaceLogicChannelCardMixin",
"ae2.helpers.PatternProviderLogicAdvancedMixin",
"ae2.helpers.PatternProviderLogicDoublingMixin",
"ae2.parts.automation.IOBusPartChannelCardMixin",
"ae2.parts.storagebus.StorageBusPartChannelCardMixin",
"ae2.menu.ContainerPatternEncodingTermMenuMixin",
"ae2.menu.MEStorageMenuMixin",
"ae2.menu.PatternEncodingTermMenuMixin",