添加了无线收发器方块,支持一对多连接提供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.ModLoadingContext;
|
||||||
import net.minecraftforge.fml.config.ModConfig;
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
import com.extendedae_plus.config.ModConfigs;
|
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类
|
* ExtendedAE Plus 主mod类
|
||||||
|
|
@ -22,6 +25,11 @@ public class ExtendedAEPlus {
|
||||||
// 注册mod初始化事件
|
// 注册mod初始化事件
|
||||||
modEventBus.addListener(this::commonSetup);
|
modEventBus.addListener(this::commonSetup);
|
||||||
|
|
||||||
|
// 注册方块与方块实体
|
||||||
|
ModBlocks.BLOCKS.register(modEventBus);
|
||||||
|
ModBlockEntities.BLOCK_ENTITY_TYPES.register(modEventBus);
|
||||||
|
ModItems.ITEMS.register(modEventBus);
|
||||||
|
|
||||||
// 注册到Forge事件总线
|
// 注册到Forge事件总线
|
||||||
MinecraftForge.EVENT_BUS.register(this);
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
public final class ModConfigs {
|
public final class ModConfigs {
|
||||||
public static final ForgeConfigSpec COMMON_SPEC;
|
public static final ForgeConfigSpec COMMON_SPEC;
|
||||||
public static final ForgeConfigSpec.IntValue PAGE_MULTIPLIER;
|
public static final ForgeConfigSpec.IntValue PAGE_MULTIPLIER;
|
||||||
|
public static final ForgeConfigSpec.DoubleValue WIRELESS_MAX_RANGE;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
|
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
|
||||||
|
|
@ -15,6 +16,14 @@ public final class ModConfigs {
|
||||||
"基础为36,每页仍显示36格,倍率会增加总页数/总容量。",
|
"基础为36,每页仍显示36格,倍率会增加总页数/总容量。",
|
||||||
"建议范围 1-16")
|
"建议范围 1-16")
|
||||||
.defineInRange("pageMultiplier", 1, 1, 64);
|
.defineInRange("pageMultiplier", 1, 1, 64);
|
||||||
|
|
||||||
|
// 无线收发器:最大连接距离(单位:方块)。
|
||||||
|
// 一对多从端连接主端时,将以该值作为范围限制。
|
||||||
|
WIRELESS_MAX_RANGE = builder
|
||||||
|
.comment(
|
||||||
|
"无线收发器最大连接距离(单位:方块)",
|
||||||
|
"从端与主端的直线距离需小于等于该值才会建立连接。")
|
||||||
|
.defineInRange("wirelessMaxRange", 256.0D, 1.0D, 4096.0D);
|
||||||
builder.pop();
|
builder.pop();
|
||||||
COMMON_SPEC = builder.build();
|
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.toggle_slots": "切换槽位显示",
|
||||||
"gui.expatternprovider.hide_slots": "隐藏槽位",
|
"gui.expatternprovider.hide_slots": "隐藏槽位",
|
||||||
"gui.expatternprovider.show_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