添加了无线收发器方块,支持一对多连接提供me频道
This commit is contained in:
parent
319253d6f9
commit
3d2e7b7165
|
|
@ -7,6 +7,9 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
|||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import com.extendedae_plus.config.ModConfigs;
|
||||
import com.extendedae_plus.init.ModBlocks;
|
||||
import com.extendedae_plus.init.ModBlockEntities;
|
||||
import com.extendedae_plus.init.ModItems;
|
||||
|
||||
/**
|
||||
* ExtendedAE Plus 主mod类
|
||||
|
|
@ -22,6 +25,11 @@ public class ExtendedAEPlus {
|
|||
// 注册mod初始化事件
|
||||
modEventBus.addListener(this::commonSetup);
|
||||
|
||||
// 注册方块与方块实体
|
||||
ModBlocks.BLOCKS.register(modEventBus);
|
||||
ModBlockEntities.BLOCK_ENTITY_TYPES.register(modEventBus);
|
||||
ModItems.ITEMS.register(modEventBus);
|
||||
|
||||
// 注册到Forge事件总线
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import net.minecraftforge.common.ForgeConfigSpec;
|
|||
public final class ModConfigs {
|
||||
public static final ForgeConfigSpec COMMON_SPEC;
|
||||
public static final ForgeConfigSpec.IntValue PAGE_MULTIPLIER;
|
||||
public static final ForgeConfigSpec.DoubleValue WIRELESS_MAX_RANGE;
|
||||
|
||||
static {
|
||||
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
|
||||
|
|
@ -15,6 +16,14 @@ public final class ModConfigs {
|
|||
"基础为36,每页仍显示36格,倍率会增加总页数/总容量。",
|
||||
"建议范围 1-16")
|
||||
.defineInRange("pageMultiplier", 1, 1, 64);
|
||||
|
||||
// 无线收发器:最大连接距离(单位:方块)。
|
||||
// 一对多从端连接主端时,将以该值作为范围限制。
|
||||
WIRELESS_MAX_RANGE = builder
|
||||
.comment(
|
||||
"无线收发器最大连接距离(单位:方块)",
|
||||
"从端与主端的直线距离需小于等于该值才会建立连接。")
|
||||
.defineInRange("wirelessMaxRange", 256.0D, 1.0D, 4096.0D);
|
||||
builder.pop();
|
||||
COMMON_SPEC = builder.build();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
package com.extendedae_plus.content.wireless;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.extendedae_plus.init.ModBlockEntities;
|
||||
|
||||
public class WirelessTransceiverBlock extends Block implements EntityBlock {
|
||||
public WirelessTransceiverBlock(Properties props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new WirelessTransceiverBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
|
||||
if (level.isClientSide) {
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
BlockEntity be = level.getBlockEntity(pos);
|
||||
if (be instanceof WirelessTransceiverBlockEntity te) {
|
||||
boolean sneaking = player.isShiftKeyDown();
|
||||
if (sneaking) {
|
||||
// 简单演示:Shift+右键 频率+1
|
||||
long f = te.getFrequency();
|
||||
te.setFrequency(f + 1);
|
||||
player.displayClientMessage(net.minecraft.network.chat.Component.literal("Freq: " + te.getFrequency()), true);
|
||||
} else {
|
||||
te.setMasterMode(!te.isMasterMode());
|
||||
player.displayClientMessage(net.minecraft.network.chat.Component.literal(te.isMasterMode() ? "Mode: MASTER" : "Mode: SLAVE"), true);
|
||||
}
|
||||
return InteractionResult.CONSUME;
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
if (!state.is(newState.getBlock())) {
|
||||
BlockEntity be = level.getBlockEntity(pos);
|
||||
if (be instanceof WirelessTransceiverBlockEntity te) {
|
||||
te.onRemoved();
|
||||
}
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, isMoving);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
|
||||
if (level.isClientSide) return null;
|
||||
return type == ModBlockEntities.WIRELESS_TRANSCEIVER_BE.get()
|
||||
? (lvl, pos, st, be) -> WirelessTransceiverBlockEntity.serverTick(lvl, pos, st, (WirelessTransceiverBlockEntity) be)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
package com.extendedae_plus.content.wireless;
|
||||
|
||||
import appeng.api.networking.GridHelper;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.IGridNodeListener;
|
||||
import appeng.api.networking.IManagedGridNode;
|
||||
import appeng.api.networking.IInWorldGridNodeHost;
|
||||
import com.extendedae_plus.wireless.IWirelessEndpoint;
|
||||
import com.extendedae_plus.wireless.WirelessMasterLink;
|
||||
import com.extendedae_plus.wireless.WirelessSlaveLink;
|
||||
import com.extendedae_plus.init.ModBlockEntities;
|
||||
import com.extendedae_plus.init.ModItems;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.core.Direction;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* 无线收发器方块实体(骨架):
|
||||
* - 主/从模式切换;
|
||||
* - 频率设置;
|
||||
* - 集成 AE2 节点;
|
||||
* - 集成无线主/从逻辑。
|
||||
*
|
||||
* 注意:本类不包含注册常量,需在你的注册系统中完成 BlockEntityType 的创建与绑定。
|
||||
*/
|
||||
public class WirelessTransceiverBlockEntity extends BlockEntity implements IWirelessEndpoint, IInWorldGridNodeHost {
|
||||
|
||||
private IManagedGridNode managedNode;
|
||||
|
||||
private long frequency = 0L;
|
||||
private boolean masterMode = true;
|
||||
|
||||
private WirelessMasterLink masterLink;
|
||||
private WirelessSlaveLink slaveLink;
|
||||
|
||||
public WirelessTransceiverBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(ModBlockEntities.WIRELESS_TRANSCEIVER_BE.get(), pos, state);
|
||||
// 创建 AE2 管理节点
|
||||
this.managedNode = GridHelper.createManagedNode(this, NodeListener.INSTANCE);
|
||||
this.managedNode.setIdlePowerUsage(1.0); // 可按需调整基础待机功耗
|
||||
this.managedNode.setTagName("wireless_node");
|
||||
this.managedNode.setInWorldNode(true);
|
||||
this.managedNode.setExposedOnSides(EnumSet.allOf(Direction.class));
|
||||
// 可见表示,方便在 AE2 界面中识别(可选)
|
||||
this.managedNode.setVisualRepresentation(ModItems.WIRELESS_TRANSCEIVER.get().getDefaultInstance());
|
||||
// 初始化无线逻辑
|
||||
this.masterLink = new WirelessMasterLink(this);
|
||||
this.slaveLink = new WirelessSlaveLink(this);
|
||||
}
|
||||
|
||||
/* ===================== IInWorldGridNodeHost ===================== */
|
||||
@Override
|
||||
public @Nullable IGridNode getGridNode(Direction dir) {
|
||||
return getGridNode();
|
||||
}
|
||||
|
||||
/* ===================== IWirelessEndpoint ===================== */
|
||||
@Override
|
||||
public ServerLevel getServerLevel() {
|
||||
Level lvl = super.getLevel();
|
||||
return lvl instanceof ServerLevel sl ? sl : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getBlockPos() {
|
||||
return this.worldPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGridNode getGridNode() {
|
||||
return managedNode == null ? null : managedNode.getNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEndpointRemoved() {
|
||||
return super.isRemoved();
|
||||
}
|
||||
|
||||
/* ===================== 公共方法(交互调用) ===================== */
|
||||
public long getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public void setFrequency(long frequency) {
|
||||
if (this.frequency == frequency) return;
|
||||
this.frequency = frequency;
|
||||
if (isMasterMode()) {
|
||||
masterLink.setFrequency(frequency);
|
||||
} else {
|
||||
slaveLink.setFrequency(frequency);
|
||||
}
|
||||
setChanged();
|
||||
}
|
||||
|
||||
public boolean isMasterMode() {
|
||||
return masterMode;
|
||||
}
|
||||
|
||||
public void setMasterMode(boolean masterMode) {
|
||||
if (this.masterMode == masterMode) return;
|
||||
// 切换前清理原模式状态
|
||||
if (this.masterMode) {
|
||||
masterLink.onUnloadOrRemove();
|
||||
} else {
|
||||
slaveLink.onUnloadOrRemove();
|
||||
}
|
||||
this.masterMode = masterMode;
|
||||
// 切换后应用频率
|
||||
if (this.masterMode) {
|
||||
masterLink.setFrequency(frequency);
|
||||
} else {
|
||||
slaveLink.setFrequency(frequency);
|
||||
}
|
||||
setChanged();
|
||||
}
|
||||
|
||||
public void onRemoved() {
|
||||
if (this.masterMode) {
|
||||
masterLink.onUnloadOrRemove();
|
||||
} else {
|
||||
slaveLink.onUnloadOrRemove();
|
||||
}
|
||||
if (managedNode != null) {
|
||||
managedNode.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/* ===================== Tick ===================== */
|
||||
public static void serverTick(Level level, BlockPos pos, BlockState state, WirelessTransceiverBlockEntity be) {
|
||||
if (!(level instanceof ServerLevel)) return;
|
||||
if (!be.masterMode) {
|
||||
// 从端需要周期检查与维护连接
|
||||
be.slaveLink.updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
super.onLoad();
|
||||
// 仅服务端创建节点
|
||||
ServerLevel sl = getServerLevel();
|
||||
if (sl == null) return;
|
||||
// 在首个 tick 创建,以保证区块已就绪
|
||||
GridHelper.onFirstTick(this, be -> {
|
||||
be.managedNode.create(be.getLevel(), be.getBlockPos());
|
||||
});
|
||||
}
|
||||
|
||||
/* ===================== NBT ===================== */
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag tag) {
|
||||
super.saveAdditional(tag);
|
||||
tag.putLong("frequency", frequency);
|
||||
tag.putBoolean("master", masterMode);
|
||||
if (managedNode != null) {
|
||||
managedNode.saveToNBT(tag);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(CompoundTag tag) {
|
||||
super.load(tag);
|
||||
this.frequency = tag.getLong("frequency");
|
||||
this.masterMode = tag.getBoolean("master");
|
||||
if (managedNode != null) {
|
||||
managedNode.loadFromNBT(tag);
|
||||
}
|
||||
// 应用到链接器
|
||||
if (masterMode) {
|
||||
masterLink.setFrequency(frequency);
|
||||
} else {
|
||||
slaveLink.setFrequency(frequency);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===================== AE2 节点监听 ===================== */
|
||||
enum NodeListener implements IGridNodeListener<WirelessTransceiverBlockEntity> {
|
||||
INSTANCE;
|
||||
@Override
|
||||
public void onSaveChanges(WirelessTransceiverBlockEntity host, IGridNode node) {
|
||||
host.setChanged();
|
||||
}
|
||||
@Override
|
||||
public void onStateChanged(WirelessTransceiverBlockEntity host, IGridNode node, State state) {
|
||||
// 可在此响应 POWER/CHANNEL 等变化,刷新显示等
|
||||
}
|
||||
@Override
|
||||
public void onInWorldConnectionChanged(WirelessTransceiverBlockEntity host, IGridNode node) {}
|
||||
@Override
|
||||
public void onGridChanged(WirelessTransceiverBlockEntity host, IGridNode node) {}
|
||||
@Override
|
||||
public void onOwnerChanged(WirelessTransceiverBlockEntity host, IGridNode node) {}
|
||||
}
|
||||
}
|
||||
20
src/main/java/com/extendedae_plus/init/ModBlockEntities.java
Normal file
20
src/main/java/com/extendedae_plus/init/ModBlockEntities.java
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package com.extendedae_plus.init;
|
||||
|
||||
import com.extendedae_plus.ExtendedAEPlus;
|
||||
import com.extendedae_plus.content.wireless.WirelessTransceiverBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
|
||||
public final class ModBlockEntities {
|
||||
private ModBlockEntities() {}
|
||||
|
||||
public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITY_TYPES =
|
||||
DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, ExtendedAEPlus.MODID);
|
||||
|
||||
public static final RegistryObject<BlockEntityType<WirelessTransceiverBlockEntity>> WIRELESS_TRANSCEIVER_BE =
|
||||
BLOCK_ENTITY_TYPES.register("wireless_transceiver",
|
||||
() -> BlockEntityType.Builder.of(WirelessTransceiverBlockEntity::new,
|
||||
ModBlocks.WIRELESS_TRANSCEIVER.get()).build(null));
|
||||
}
|
||||
21
src/main/java/com/extendedae_plus/init/ModBlocks.java
Normal file
21
src/main/java/com/extendedae_plus/init/ModBlocks.java
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package com.extendedae_plus.init;
|
||||
|
||||
import com.extendedae_plus.ExtendedAEPlus;
|
||||
import com.extendedae_plus.content.wireless.WirelessTransceiverBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.material.MapColor;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
|
||||
public final class ModBlocks {
|
||||
private ModBlocks() {}
|
||||
|
||||
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, ExtendedAEPlus.MODID);
|
||||
|
||||
public static final RegistryObject<Block> WIRELESS_TRANSCEIVER = BLOCKS.register(
|
||||
"wireless_transceiver",
|
||||
() -> new WirelessTransceiverBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).strength(2.0F, 6.0F))
|
||||
);
|
||||
}
|
||||
20
src/main/java/com/extendedae_plus/init/ModItems.java
Normal file
20
src/main/java/com/extendedae_plus/init/ModItems.java
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package com.extendedae_plus.init;
|
||||
|
||||
import com.extendedae_plus.ExtendedAEPlus;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
|
||||
public final class ModItems {
|
||||
private ModItems() {}
|
||||
|
||||
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, ExtendedAEPlus.MODID);
|
||||
|
||||
public static final RegistryObject<Item> WIRELESS_TRANSCEIVER = ITEMS.register(
|
||||
"wireless_transceiver",
|
||||
() -> new BlockItem(ModBlocks.WIRELESS_TRANSCEIVER.get(), new Item.Properties())
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.extendedae_plus.wireless;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
|
||||
/**
|
||||
* 无线端点最小接口。
|
||||
* 你的无线收发器方块实体需实现该接口,
|
||||
* 以便无线逻辑能够获取世界、位置与 AE2 节点。
|
||||
*/
|
||||
public interface IWirelessEndpoint {
|
||||
/** 返回方块所在的服务端世界(避免与 BlockEntity#getLevel 冲突) */
|
||||
ServerLevel getServerLevel();
|
||||
|
||||
/** 返回方块位置 */
|
||||
BlockPos getBlockPos();
|
||||
|
||||
/** 返回可用于 AE2 连接的节点(通常为主节点) */
|
||||
IGridNode getGridNode();
|
||||
|
||||
/** 是否已移除/销毁(端点视角),用于在卸载或破坏时停止连接 */
|
||||
boolean isEndpointRemoved();
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package com.extendedae_plus.wireless;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
|
||||
/**
|
||||
* 主收发器端逻辑:负责在频率变化/加载时向注册中心登记唯一主端,卸载时反注册。
|
||||
* 方块实体应在合适的生命周期中调用 register/unregister。
|
||||
*/
|
||||
public class WirelessMasterLink {
|
||||
private final IWirelessEndpoint host;
|
||||
private long frequency; // 0 为未设置
|
||||
private boolean registered;
|
||||
|
||||
public WirelessMasterLink(IWirelessEndpoint host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public long getFrequency() { return frequency; }
|
||||
|
||||
public void setFrequency(long frequency) {
|
||||
if (this.frequency == frequency) return;
|
||||
// 先反注册旧频率
|
||||
if (registered) {
|
||||
unregister();
|
||||
}
|
||||
this.frequency = frequency;
|
||||
// 再尝试注册新频率
|
||||
if (frequency != 0L && !host.isEndpointRemoved()) {
|
||||
register();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean register() {
|
||||
ServerLevel level = host.getServerLevel();
|
||||
if (level == null || frequency == 0L) return false;
|
||||
boolean ok = WirelessMasterRegistry.register(level, frequency, host);
|
||||
this.registered = ok;
|
||||
return ok;
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
ServerLevel level = host.getServerLevel();
|
||||
if (!registered || level == null || frequency == 0L) return;
|
||||
WirelessMasterRegistry.unregister(level, frequency, host);
|
||||
registered = false;
|
||||
}
|
||||
|
||||
public void onUnloadOrRemove() {
|
||||
unregister();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package com.extendedae_plus.wireless;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 无线主端注册中心:按 维度 + 频率 唯一注册一个主收发器端点。
|
||||
* 从端通过本注册中心按频率查找主端,实现一对多连接。
|
||||
*/
|
||||
public final class WirelessMasterRegistry {
|
||||
private WirelessMasterRegistry() {}
|
||||
|
||||
private static final Map<Key, WeakReference<IWirelessEndpoint>> MASTERS = new HashMap<>();
|
||||
|
||||
public static synchronized boolean register(ServerLevel level, long frequency, IWirelessEndpoint endpoint) {
|
||||
Objects.requireNonNull(level, "level");
|
||||
Objects.requireNonNull(endpoint, "endpoint");
|
||||
if (frequency == 0L) return false;
|
||||
final Key key = new Key(level.dimension(), frequency);
|
||||
cleanupIfCleared(key);
|
||||
var existing = MASTERS.get(key);
|
||||
var existingVal = existing == null ? null : existing.get();
|
||||
if (existingVal != null && !existingVal.isEndpointRemoved()) {
|
||||
// 同维度同频率已经有主端
|
||||
return false;
|
||||
}
|
||||
MASTERS.put(key, new WeakReference<>(endpoint));
|
||||
return true;
|
||||
}
|
||||
|
||||
public static synchronized void unregister(ServerLevel level, long frequency, IWirelessEndpoint endpoint) {
|
||||
if (frequency == 0L || level == null) return;
|
||||
final Key key = new Key(level.dimension(), frequency);
|
||||
var ref = MASTERS.get(key);
|
||||
if (ref != null) {
|
||||
var cur = ref.get();
|
||||
if (cur == null || cur == endpoint) {
|
||||
MASTERS.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized IWirelessEndpoint get(ServerLevel level, long frequency) {
|
||||
if (frequency == 0L || level == null) return null;
|
||||
final Key key = new Key(level.dimension(), frequency);
|
||||
cleanupIfCleared(key);
|
||||
var ref = MASTERS.get(key);
|
||||
return ref == null ? null : ref.get();
|
||||
}
|
||||
|
||||
private static void cleanupIfCleared(Key key) {
|
||||
var ref = MASTERS.get(key);
|
||||
if (ref != null && ref.get() == null) {
|
||||
MASTERS.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
private record Key(ResourceKey<Level> dim, long freq) {
|
||||
@Override public String toString() { return dim.location() + "#" + freq; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package com.extendedae_plus.wireless;
|
||||
|
||||
import appeng.api.networking.GridHelper;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.me.service.helpers.ConnectionWrapper;
|
||||
import com.extendedae_plus.config.ModConfigs;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 从收发器连接器:
|
||||
* - 通过频率查找同维度主收发器;
|
||||
* - 校验距离(<= ModConfigs.WIRELESS_MAX_RANGE);
|
||||
* - 动态创建/销毁 AE2 连接(GridConnection),实现“一主多从”。
|
||||
*/
|
||||
public class WirelessSlaveLink {
|
||||
private final IWirelessEndpoint host;
|
||||
private long frequency; // 0 未设置
|
||||
|
||||
private ConnectionWrapper connection = new ConnectionWrapper(null);
|
||||
private boolean shutdown = true;
|
||||
private double distance;
|
||||
|
||||
public WirelessSlaveLink(IWirelessEndpoint host) {
|
||||
this.host = Objects.requireNonNull(host);
|
||||
}
|
||||
|
||||
public void setFrequency(long frequency) {
|
||||
if (this.frequency != frequency) {
|
||||
this.frequency = frequency;
|
||||
// 频率变更,立即尝试重连/断开
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
public long getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return !shutdown && connection.getConnection() != null;
|
||||
}
|
||||
|
||||
public double getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 建议在 BE 的 serverTick 或者频率/加载状态变化时调用。
|
||||
*/
|
||||
public void updateStatus() {
|
||||
if (host.isEndpointRemoved()) {
|
||||
destroyConnection();
|
||||
return;
|
||||
}
|
||||
final ServerLevel level = host.getServerLevel();
|
||||
if (level == null || frequency == 0L) {
|
||||
destroyConnection();
|
||||
return;
|
||||
}
|
||||
|
||||
IWirelessEndpoint master = WirelessMasterRegistry.get(level, frequency);
|
||||
shutdown = false;
|
||||
distance = 0.0D;
|
||||
|
||||
if (master != null && !master.isEndpointRemoved() && master.getServerLevel() == level) {
|
||||
distance = Math.sqrt(master.getBlockPos().distSqr(host.getBlockPos()));
|
||||
double maxRange = ModConfigs.WIRELESS_MAX_RANGE.get();
|
||||
if (distance <= maxRange) {
|
||||
// 保持/建立连接
|
||||
try {
|
||||
var current = connection.getConnection();
|
||||
IGridNode a = host.getGridNode(); // 从端
|
||||
IGridNode b = master.getGridNode(); // 主端
|
||||
if (a == null || b == null) {
|
||||
shutdown = true;
|
||||
} else {
|
||||
if (current != null) {
|
||||
// 如果已连且目标相同则维持
|
||||
var ca = current.a();
|
||||
var cb = current.b();
|
||||
if ((ca == a || cb == a) && (ca == b || cb == b)) {
|
||||
return; // 连接已正确
|
||||
}
|
||||
// 否则先断开,再重建
|
||||
current.destroy();
|
||||
connection = new ConnectionWrapper(null);
|
||||
}
|
||||
connection = new ConnectionWrapper(GridHelper.createConnection(a, b));
|
||||
return;
|
||||
}
|
||||
} catch (IllegalStateException ignore) {
|
||||
// 连接非法(如重复连接等)——落入重建/关闭逻辑
|
||||
}
|
||||
} else {
|
||||
shutdown = true; // 超出范围
|
||||
}
|
||||
} else {
|
||||
shutdown = true; // 无主或主端不可用/不同维度
|
||||
}
|
||||
|
||||
// 需要关闭连接
|
||||
destroyConnection();
|
||||
}
|
||||
|
||||
public void onUnloadOrRemove() {
|
||||
destroyConnection();
|
||||
}
|
||||
|
||||
private void destroyConnection() {
|
||||
var current = connection.getConnection();
|
||||
if (current != null) {
|
||||
current.destroy();
|
||||
connection.setConnection(null);
|
||||
}
|
||||
connection = new ConnectionWrapper(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"variants": {
|
||||
"": { "model": "extendedae_plus:block/wireless_transceiver" }
|
||||
}
|
||||
}
|
||||
|
|
@ -2,5 +2,7 @@
|
|||
"gui.expatternprovider.toggle_slots": "切换槽位显示",
|
||||
"gui.expatternprovider.hide_slots": "隐藏槽位",
|
||||
"gui.expatternprovider.show_slots": "显示槽位",
|
||||
"gui.expatternprovider.clear_selection": "取消选择"
|
||||
}
|
||||
"gui.expatternprovider.clear_selection": "取消选择",
|
||||
"block.extendedae_plus.wireless_transceiver": "无线收发器",
|
||||
"item.extendedae_plus.wireless_transceiver": "无线收发器"
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "minecraft:block/iron_block"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "extendedae_plus:block/wireless_transceiver"
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "extendedae_plus:wireless_transceiver"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user