为无线收发器绑定ftbteams
This commit is contained in:
parent
60c5dc7cf7
commit
b31ec61b54
|
|
@ -123,6 +123,8 @@ dependencies {
|
|||
modImplementation "curse.maven:configuration-444699:4710266"
|
||||
|
||||
//ftbteams
|
||||
modCompileOnly "curse.maven:ftb-teams-forge-404468:6130786"
|
||||
modCompileOnly "curse.maven:ftb-library-forge-404465:6807424"
|
||||
modRuntimeOnly "curse.maven:ftb-teams-forge-404468:6130786"
|
||||
modRuntimeOnly "curse.maven:ftb-library-forge-404465:6807424"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
package com.extendedae_plus.ae.items;
|
||||
|
||||
import appeng.items.materials.UpgradeCardItem;
|
||||
import com.extendedae_plus.util.WirelessTeamUtil;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
|
|
@ -13,13 +15,19 @@ import net.minecraft.world.level.Level;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 频道卡(MVP):仅存储一个 long 类型的频道号到 NBT:"channel"。
|
||||
* 频道卡:存储频道号、所有者UUID和团队信息
|
||||
* - 右键空气:增加频道号
|
||||
* - 潜行左键空气:写入/清除玩家UUID和团队信息
|
||||
* - 潜行左键收发器:将频道卡的所有者信息写入收发器
|
||||
* 继承 AE2 的 UpgradeCardItem 以复用升级卡判定与提示框架。
|
||||
*/
|
||||
public class ChannelCardItem extends UpgradeCardItem {
|
||||
public static final String TAG_CHANNEL = "channel";
|
||||
public static final String TAG_OWNER_UUID = "ownerUUID";
|
||||
public static final String TAG_TEAM_NAME = "teamName"; // 用于显示
|
||||
|
||||
public ChannelCardItem(Item.Properties properties) {
|
||||
super(properties);
|
||||
|
|
@ -35,29 +43,157 @@ public class ChannelCardItem extends UpgradeCardItem {
|
|||
return tag != null && tag.contains(TAG_CHANNEL) ? tag.getLong(TAG_CHANNEL) : 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置频道卡的所有者UUID
|
||||
*/
|
||||
public static void setOwnerUUID(ItemStack stack, UUID ownerUUID) {
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
tag.putUUID(TAG_OWNER_UUID, ownerUUID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取频道卡的所有者UUID
|
||||
*/
|
||||
@Nullable
|
||||
public static UUID getOwnerUUID(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
return tag != null && tag.hasUUID(TAG_OWNER_UUID) ? tag.getUUID(TAG_OWNER_UUID) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置团队名称(用于显示)
|
||||
*/
|
||||
public static void setTeamName(ItemStack stack, String teamName) {
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
tag.putString(TAG_TEAM_NAME, teamName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取团队名称
|
||||
*/
|
||||
@Nullable
|
||||
public static String getTeamName(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
return tag != null && tag.contains(TAG_TEAM_NAME) ? tag.getString(TAG_TEAM_NAME) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有者信息
|
||||
*/
|
||||
public static void clearOwner(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag != null) {
|
||||
tag.remove(TAG_OWNER_UUID);
|
||||
tag.remove(TAG_TEAM_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> lines, TooltipFlag flag) {
|
||||
super.appendHoverText(stack, level, 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));
|
||||
}
|
||||
|
||||
// 显示所有者信息
|
||||
UUID ownerUUID = getOwnerUUID(stack);
|
||||
String teamName = getTeamName(stack);
|
||||
|
||||
if (ownerUUID != null) {
|
||||
if (teamName != null && !teamName.isEmpty()) {
|
||||
lines.add(Component.translatable("item.extendedae_plus.channel_card.owner.team", teamName));
|
||||
} else {
|
||||
lines.add(Component.translatable("item.extendedae_plus.channel_card.owner.player", ownerUUID.toString().substring(0, 8)));
|
||||
}
|
||||
} else {
|
||||
lines.add(Component.translatable("item.extendedae_plus.channel_card.owner.unset"));
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
long next;
|
||||
|
||||
if (player.isShiftKeyDown()) {
|
||||
// 潜行右键:减少频率
|
||||
next = Math.max(0L, ch - 1L);
|
||||
} else {
|
||||
// 普通右键:增加频率
|
||||
next = 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLeftClickEntity(ItemStack stack, Player player, net.minecraft.world.entity.Entity entity) {
|
||||
// 左键实体时不做任何事,避免伤害实体
|
||||
if (player.isShiftKeyDown()) {
|
||||
return true; // 取消默认行为
|
||||
}
|
||||
return super.onLeftClickEntity(stack, player, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBlockStartBreak(ItemStack stack, net.minecraft.core.BlockPos pos, Player player) {
|
||||
// 潜行左键方块时触发绑定/解绑
|
||||
if (!player.isShiftKeyDown()) {
|
||||
return false; // 不拦截
|
||||
}
|
||||
|
||||
if (player.level().isClientSide) {
|
||||
return true; // 客户端拦截,防止破坏方块
|
||||
}
|
||||
|
||||
// 服务端处理
|
||||
if (player.level() instanceof ServerLevel serverLevel) {
|
||||
// 检查是否是收发器(让Block类处理)
|
||||
var blockState = player.level().getBlockState(pos);
|
||||
if (blockState.getBlock() instanceof com.extendedae_plus.content.wireless.WirelessTransceiverBlock) {
|
||||
return false; // 不拦截,让Block类处理
|
||||
}
|
||||
|
||||
// 执行绑定/解绑
|
||||
UUID currentOwner = getOwnerUUID(stack);
|
||||
|
||||
if (currentOwner != null) {
|
||||
// 已有所有者,清除
|
||||
clearOwner(stack);
|
||||
player.displayClientMessage(
|
||||
Component.translatable("item.extendedae_plus.channel_card.owner.cleared"),
|
||||
true
|
||||
);
|
||||
} else {
|
||||
// 写入当前玩家的UUID和团队信息
|
||||
UUID playerUUID = player.getUUID();
|
||||
setOwnerUUID(stack, playerUUID);
|
||||
|
||||
// 获取团队名称用于显示
|
||||
Component teamName = WirelessTeamUtil.getNetworkOwnerName(serverLevel, playerUUID);
|
||||
setTeamName(stack, teamName.getString());
|
||||
|
||||
player.displayClientMessage(
|
||||
Component.translatable("item.extendedae_plus.channel_card.owner.bound", teamName),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true; // 拦截,防止破坏方块
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package com.extendedae_plus.ae.wireless;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 主收发器端逻辑:负责在频率变化/加载时向注册中心登记唯一主端,卸载时反注册。
|
||||
|
|
@ -10,10 +13,16 @@ public class WirelessMasterLink {
|
|||
private final IWirelessEndpoint host;
|
||||
private long frequency; // 0 为未设置
|
||||
private boolean registered;
|
||||
@Nullable
|
||||
private UUID placerId; // 放置者UUID
|
||||
|
||||
public WirelessMasterLink(IWirelessEndpoint host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public void setPlacerId(@Nullable UUID placerId) {
|
||||
this.placerId = placerId;
|
||||
}
|
||||
|
||||
public long getFrequency() { return frequency; }
|
||||
|
||||
|
|
@ -42,16 +51,16 @@ public class WirelessMasterLink {
|
|||
|
||||
public boolean register() {
|
||||
ServerLevel level = host.getServerLevel();
|
||||
if (level == null || frequency == 0L) return false;
|
||||
boolean ok = WirelessMasterRegistry.register(level, frequency, host);
|
||||
if (level == null || frequency == 0L || placerId == null) return false;
|
||||
boolean ok = WirelessMasterRegistry.register(level, frequency, placerId, 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);
|
||||
if (!registered || level == null || frequency == 0L || placerId == null) return;
|
||||
WirelessMasterRegistry.unregister(level, frequency, placerId, host);
|
||||
registered = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,43 +1,54 @@
|
|||
package com.extendedae_plus.ae.wireless;
|
||||
|
||||
import com.extendedae_plus.config.ModConfig;
|
||||
import com.extendedae_plus.util.WirelessTeamUtil;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 无线主端注册中心:按 维度 + 频率 唯一注册一个主收发器端点。
|
||||
* 无线主端注册中心:按 维度 + 频率 + 所有者 唯一注册一个主收发器端点。
|
||||
* 从端通过本注册中心按频率查找主端,实现一对多连接。
|
||||
* 所有者隔离:有FTBTeams时同队共享,没有时每个玩家独立。
|
||||
*/
|
||||
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) {
|
||||
public static synchronized boolean register(ServerLevel level, long frequency, @Nullable UUID placerId, IWirelessEndpoint endpoint) {
|
||||
Objects.requireNonNull(level, "level");
|
||||
Objects.requireNonNull(endpoint, "endpoint");
|
||||
if (frequency == 0L) return false;
|
||||
final Key key = new Key(useGlobal() ? null : level.dimension(), frequency);
|
||||
if (frequency == 0L || placerId == null) return false;
|
||||
|
||||
// 获取网络所有者UUID(FTBTeams队伍UUID或玩家UUID)
|
||||
UUID ownerUUID = WirelessTeamUtil.getNetworkOwnerUUID(level, placerId);
|
||||
final Key key = new Key(useGlobal() ? null : level.dimension(), frequency, ownerUUID);
|
||||
|
||||
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(useGlobal() ? null : level.dimension(), frequency);
|
||||
public static synchronized void unregister(ServerLevel level, long frequency, @Nullable UUID placerId, IWirelessEndpoint endpoint) {
|
||||
if (frequency == 0L || level == null || placerId == null) return;
|
||||
|
||||
UUID ownerUUID = WirelessTeamUtil.getNetworkOwnerUUID(level, placerId);
|
||||
final Key key = new Key(useGlobal() ? null : level.dimension(), frequency, ownerUUID);
|
||||
|
||||
var ref = MASTERS.get(key);
|
||||
if (ref != null) {
|
||||
var cur = ref.get();
|
||||
|
|
@ -47,9 +58,12 @@ public final class WirelessMasterRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
public static synchronized IWirelessEndpoint get(ServerLevel level, long frequency) {
|
||||
if (frequency == 0L || level == null) return null;
|
||||
final Key key = new Key(useGlobal() ? null : level.dimension(), frequency);
|
||||
public static synchronized IWirelessEndpoint get(ServerLevel level, long frequency, @Nullable UUID placerId) {
|
||||
if (frequency == 0L || level == null || placerId == null) return null;
|
||||
|
||||
UUID ownerUUID = WirelessTeamUtil.getNetworkOwnerUUID(level, placerId);
|
||||
final Key key = new Key(useGlobal() ? null : level.dimension(), frequency, ownerUUID);
|
||||
|
||||
cleanupIfCleared(key);
|
||||
var ref = MASTERS.get(key);
|
||||
return ref == null ? null : ref.get();
|
||||
|
|
@ -66,9 +80,12 @@ public final class WirelessMasterRegistry {
|
|||
return ModConfig.INSTANCE.wirelessCrossDimEnable;
|
||||
}
|
||||
|
||||
private record Key(ResourceKey<Level> dim, long freq) {
|
||||
@Override public String toString() {
|
||||
return (dim == null ? "*" : dim.location().toString()) + "#" + freq;
|
||||
private record Key(@Nullable ResourceKey<Level> dim, long freq, UUID owner) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return (dim == null ? "*" : dim.location().toString())
|
||||
+ "#" + freq
|
||||
+ "@" + owner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,18 +5,22 @@ import appeng.api.networking.IGridNode;
|
|||
import appeng.me.service.helpers.ConnectionWrapper;
|
||||
import com.extendedae_plus.config.ModConfig;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 从收发器连接器:
|
||||
* - 通过频率查找同维度主收发器;
|
||||
* - 校验距离(<= ModConfigs.WIRELESS_MAX_RANGE);
|
||||
* - 动态创建/销毁 AE2 连接(GridConnection),实现“一主多从”。
|
||||
* - 动态创建/销毁 AE2 连接(GridConnection),实现"一主多从"。
|
||||
*/
|
||||
public class WirelessSlaveLink {
|
||||
private final IWirelessEndpoint host;
|
||||
private long frequency; // 0 未设置
|
||||
@Nullable
|
||||
private UUID placerId; // 放置者UUID
|
||||
|
||||
private ConnectionWrapper connection = new ConnectionWrapper(null);
|
||||
private boolean shutdown = true;
|
||||
|
|
@ -25,6 +29,10 @@ public class WirelessSlaveLink {
|
|||
public WirelessSlaveLink(IWirelessEndpoint host) {
|
||||
this.host = Objects.requireNonNull(host);
|
||||
}
|
||||
|
||||
public void setPlacerId(@Nullable UUID placerId) {
|
||||
this.placerId = placerId;
|
||||
}
|
||||
|
||||
public void setFrequency(long frequency) {
|
||||
if (this.frequency != frequency) {
|
||||
|
|
@ -55,12 +63,12 @@ public class WirelessSlaveLink {
|
|||
return;
|
||||
}
|
||||
final ServerLevel level = host.getServerLevel();
|
||||
if (level == null || frequency == 0L) {
|
||||
if (level == null || frequency == 0L || placerId == null) {
|
||||
destroyConnection();
|
||||
return;
|
||||
}
|
||||
|
||||
IWirelessEndpoint master = WirelessMasterRegistry.get(level, frequency);
|
||||
IWirelessEndpoint master = WirelessMasterRegistry.get(level, frequency, placerId);
|
||||
shutdown = false;
|
||||
distance = 0.0D;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
package com.extendedae_plus.client.event;
|
||||
|
||||
import com.extendedae_plus.ExtendedAEPlus;
|
||||
import com.extendedae_plus.init.ModItems;
|
||||
import com.extendedae_plus.init.ModNetwork;
|
||||
import com.extendedae_plus.network.ChannelCardBindPacket;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* 频道卡客户端事件处理器
|
||||
* 处理左键空气事件并发送网络包到服务端
|
||||
*/
|
||||
@Mod.EventBusSubscriber(modid = ExtendedAEPlus.MODID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.FORGE)
|
||||
public class ChannelCardClientHandler {
|
||||
|
||||
/**
|
||||
* 左键空气事件(仅客户端)
|
||||
*/
|
||||
@SubscribeEvent
|
||||
public static void onLeftClickEmpty(PlayerInteractEvent.LeftClickEmpty event) {
|
||||
Player player = event.getEntity();
|
||||
|
||||
// 只处理潜行
|
||||
if (!player.isShiftKeyDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否手持频道卡
|
||||
ItemStack stack = event.getItemStack();
|
||||
if (stack.getItem() != ModItems.CHANNEL_CARD.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 发送网络包到服务端
|
||||
InteractionHand hand = event.getHand();
|
||||
ModNetwork.CHANNEL.sendToServer(new ChannelCardBindPacket(hand));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
package com.extendedae_plus.content.wireless;
|
||||
|
||||
import com.extendedae_plus.ae.items.ChannelCardItem;
|
||||
import com.extendedae_plus.init.ModBlockEntities;
|
||||
import com.extendedae_plus.init.ModItems;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
|
@ -15,6 +19,9 @@ 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 java.util.UUID;
|
||||
|
||||
public class WirelessTransceiverBlock extends Block implements EntityBlock {
|
||||
public WirelessTransceiverBlock(Properties props) {
|
||||
|
|
@ -27,28 +34,71 @@ public class WirelessTransceiverBlock extends Block implements EntityBlock {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void attack(BlockState state, Level level, BlockPos pos, Player player) {
|
||||
// 潜行左键:减频(-1 或 -10)
|
||||
if (!level.isClientSide && player.isShiftKeyDown()) {
|
||||
public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
|
||||
super.setPlacedBy(level, pos, state, placer, stack);
|
||||
if (!level.isClientSide && placer instanceof Player player) {
|
||||
BlockEntity be = level.getBlockEntity(pos);
|
||||
if (be instanceof WirelessTransceiverBlockEntity te) {
|
||||
if (te.isLocked()) {
|
||||
player.displayClientMessage(Component.literal("收发器已锁定,无法修改频道"), true);
|
||||
te.setPlacerId(player.getUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attack(BlockState state, Level level, BlockPos pos, Player player) {
|
||||
if (!level.isClientSide) {
|
||||
BlockEntity be = level.getBlockEntity(pos);
|
||||
if (be instanceof WirelessTransceiverBlockEntity te) {
|
||||
ItemStack mainHand = player.getMainHandItem();
|
||||
|
||||
// 潜行左键频道卡:写入频道卡信息到收发器
|
||||
if (player.isShiftKeyDown() && mainHand.getItem() == ModItems.CHANNEL_CARD.get()) {
|
||||
handleChannelCardBinding(te, mainHand, player);
|
||||
super.attack(state, level, pos, player);
|
||||
return;
|
||||
}
|
||||
int step = 1;
|
||||
if (player.getMainHandItem().is(Items.REDSTONE_TORCH)) step = 10;
|
||||
if (player.getMainHandItem().is(Items.STICK)) step = 10;
|
||||
long f = te.getFrequency();
|
||||
f -= step;
|
||||
if (f < 0) f = 0;
|
||||
te.setFrequency(f);
|
||||
player.displayClientMessage(Component.literal("频道:" + te.getFrequency()), true);
|
||||
|
||||
// 潜行左键(其他物品):减频(-1 或 -10)
|
||||
if (player.isShiftKeyDown()) {
|
||||
if (te.isLocked()) {
|
||||
player.displayClientMessage(Component.literal("收发器已锁定,无法修改频道"), true);
|
||||
super.attack(state, level, pos, player);
|
||||
return;
|
||||
}
|
||||
int step = 1;
|
||||
if (mainHand.is(Items.REDSTONE_TORCH)) step = 10;
|
||||
if (mainHand.is(Items.STICK)) step = 10;
|
||||
long f = te.getFrequency();
|
||||
f -= step;
|
||||
if (f < 0) f = 0;
|
||||
te.setFrequency(f);
|
||||
player.displayClientMessage(Component.literal("频道:" + te.getFrequency()), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.attack(state, level, pos, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理频道卡绑定到收发器
|
||||
*/
|
||||
private void handleChannelCardBinding(WirelessTransceiverBlockEntity te, ItemStack channelCard, Player player) {
|
||||
UUID cardOwner = ChannelCardItem.getOwnerUUID(channelCard);
|
||||
|
||||
if (cardOwner != null) {
|
||||
// 写入频道卡的所有者到收发器
|
||||
te.setPlacerId(cardOwner);
|
||||
String teamName = ChannelCardItem.getTeamName(channelCard);
|
||||
player.displayClientMessage(
|
||||
Component.literal("已将收发器绑定至:" + (teamName != null ? teamName : cardOwner.toString().substring(0, 8))),
|
||||
true
|
||||
);
|
||||
} else {
|
||||
// 频道卡未绑定所有者,使用当前玩家
|
||||
te.setPlacerId(player.getUUID());
|
||||
player.displayClientMessage(Component.literal("频道卡未绑定,已使用当前玩家"), true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 无线收发器方块实体(骨架):
|
||||
|
|
@ -25,6 +26,7 @@ import java.util.Objects;
|
|||
* - 频率设置;
|
||||
* - 集成 AE2 节点;
|
||||
* - 集成无线主/从逻辑。
|
||||
* - 支持FTBTeams队伍隔离(软依赖)
|
||||
*/
|
||||
public class WirelessTransceiverBlockEntity extends AEBaseBlockEntity implements IWirelessEndpoint, IInWorldGridNodeHost {
|
||||
|
||||
|
|
@ -33,6 +35,9 @@ public class WirelessTransceiverBlockEntity extends AEBaseBlockEntity implements
|
|||
private long frequency = 1L;
|
||||
private boolean masterMode = false;
|
||||
private boolean locked = false;
|
||||
|
||||
@Nullable
|
||||
private UUID placerId; // 放置者UUID,用于队伍隔离
|
||||
|
||||
private WirelessMasterLink masterLink;
|
||||
private WirelessSlaveLink slaveLink;
|
||||
|
|
@ -96,6 +101,30 @@ public class WirelessTransceiverBlockEntity extends AEBaseBlockEntity implements
|
|||
}
|
||||
|
||||
/* ===================== 公共方法(交互调用) ===================== */
|
||||
|
||||
/**
|
||||
* 设置放置者UUID(在方块放置时调用)
|
||||
*/
|
||||
public void setPlacerId(@Nullable UUID placerId) {
|
||||
if (this.placerId != null && !this.placerId.equals(placerId)) {
|
||||
// 如果所有者改变,需要重新注册
|
||||
if (this.masterMode) {
|
||||
masterLink.onUnloadOrRemove();
|
||||
} else {
|
||||
slaveLink.onUnloadOrRemove();
|
||||
}
|
||||
}
|
||||
this.placerId = placerId;
|
||||
this.masterLink.setPlacerId(placerId);
|
||||
this.slaveLink.setPlacerId(placerId);
|
||||
setChanged();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public UUID getPlacerId() {
|
||||
return placerId;
|
||||
}
|
||||
|
||||
public long getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
|
@ -192,6 +221,9 @@ public class WirelessTransceiverBlockEntity extends AEBaseBlockEntity implements
|
|||
tag.putLong("frequency", frequency);
|
||||
tag.putBoolean("master", masterMode);
|
||||
tag.putBoolean("locked", locked);
|
||||
if (placerId != null) {
|
||||
tag.putUUID("placerId", placerId);
|
||||
}
|
||||
if (managedNode != null) {
|
||||
managedNode.saveToNBT(tag);
|
||||
}
|
||||
|
|
@ -203,6 +235,12 @@ public class WirelessTransceiverBlockEntity extends AEBaseBlockEntity implements
|
|||
this.frequency = tag.getLong("frequency");
|
||||
this.masterMode = tag.getBoolean("master");
|
||||
this.locked = tag.getBoolean("locked");
|
||||
|
||||
if (tag.hasUUID("placerId")) {
|
||||
this.placerId = tag.getUUID("placerId");
|
||||
this.masterLink.setPlacerId(this.placerId);
|
||||
this.slaveLink.setPlacerId(this.placerId);
|
||||
}
|
||||
|
||||
if (managedNode != null) {
|
||||
managedNode.loadFromNBT(tag);
|
||||
|
|
|
|||
|
|
@ -125,6 +125,12 @@ public class ModNetwork {
|
|||
.decoder(CraftingMonitorOpenProviderC2SPacket::decode)
|
||||
.consumerNetworkThread(CraftingMonitorOpenProviderC2SPacket::handle)
|
||||
.add();
|
||||
|
||||
CHANNEL.messageBuilder(ChannelCardBindPacket.class, nextId(), NetworkDirection.PLAY_TO_SERVER)
|
||||
.encoder(ChannelCardBindPacket::encode)
|
||||
.decoder(ChannelCardBindPacket::decode)
|
||||
.consumerNetworkThread(ChannelCardBindPacket::handle)
|
||||
.add();
|
||||
}
|
||||
|
||||
private static int nextId() { return id++; }
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ public enum WirelessTransceiverProvider implements IServerDataProvider<BlockAcce
|
|||
if (!blockEntity.isMasterMode()) {
|
||||
var level = blockEntity.getServerLevel();
|
||||
long freq = blockEntity.getFrequency();
|
||||
IWirelessEndpoint master = WirelessMasterRegistry.get(level, freq);
|
||||
var placerId = blockEntity.getPlacerId(); // 获取放置者UUID
|
||||
IWirelessEndpoint master = WirelessMasterRegistry.get(level, freq, placerId);
|
||||
if (master != null && !master.isEndpointRemoved()) {
|
||||
if (master instanceof WirelessTransceiverBlockEntity masterBlockEntity && masterBlockEntity.getCustomName() != null) {
|
||||
data.putString("customName", masterBlockEntity.getCustomName().getString());
|
||||
|
|
|
|||
|
|
@ -253,6 +253,11 @@ public abstract class PatternProviderLogicCompatMixin implements IUpgradeableObj
|
|||
for (ItemStack stack : upgrades) {
|
||||
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
|
||||
channel = ChannelCardItem.getChannel(stack);
|
||||
java.util.UUID ownerUUID = ChannelCardItem.getOwnerUUID(stack);
|
||||
if (ownerUUID != null) {
|
||||
// 保存ownerUUID到局部变量,后面设置到link
|
||||
channel |= ((long) ownerUUID.hashCode() << 32); // 临时存储
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -274,6 +279,18 @@ public abstract class PatternProviderLogicCompatMixin implements IUpgradeableObj
|
|||
eap$compatLink = new WirelessSlaveLink(endpoint);
|
||||
}
|
||||
|
||||
// 从频道卡重新读取ownerUUID并设置
|
||||
java.util.UUID cardOwner = null;
|
||||
if (upgrades != null) {
|
||||
for (ItemStack stack : upgrades) {
|
||||
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
|
||||
cardOwner = ChannelCardItem.getOwnerUUID(stack);
|
||||
channel = ChannelCardItem.getChannel(stack); // 重新读取正确的频率
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
eap$compatLink.setPlacerId(cardOwner);
|
||||
eap$compatLink.setFrequency(channel);
|
||||
eap$compatLink.updateStatus();
|
||||
|
||||
|
|
|
|||
|
|
@ -106,10 +106,12 @@ public abstract class InterfaceLogicChannelCardMixin implements IInterfaceWirele
|
|||
|
||||
try {
|
||||
long channel = 0L;
|
||||
java.util.UUID ownerUUID = null;
|
||||
boolean found = false;
|
||||
for (ItemStack stack : getUpgrades()) {
|
||||
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
|
||||
channel = ChannelCardItem.getChannel(stack);
|
||||
ownerUUID = ChannelCardItem.getOwnerUUID(stack);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -130,6 +132,8 @@ public abstract class InterfaceLogicChannelCardMixin implements IInterfaceWirele
|
|||
eap$link = new WirelessSlaveLink(endpoint);
|
||||
}
|
||||
|
||||
// 设置频道卡的所有者UUID(如果有的话)
|
||||
eap$link.setPlacerId(ownerUUID);
|
||||
eap$link.setFrequency(channel);
|
||||
eap$link.updateStatus();
|
||||
|
||||
|
|
|
|||
|
|
@ -71,10 +71,12 @@ public abstract class IOBusPartChannelCardMixin implements IInterfaceWirelessLin
|
|||
try {
|
||||
IUpgradeInventory inv = this.getUpgrades();
|
||||
long channel = 0L;
|
||||
java.util.UUID ownerUUID = null;
|
||||
boolean found = false;
|
||||
for (var stack : inv) {
|
||||
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
|
||||
channel = ChannelCardItem.getChannel(stack);
|
||||
ownerUUID = ChannelCardItem.getOwnerUUID(stack);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -109,6 +111,8 @@ public abstract class IOBusPartChannelCardMixin implements IInterfaceWirelessLin
|
|||
Logger.EAP$LOGGER.debug("[服务端] IOBus 创建新的无线链接");
|
||||
}
|
||||
|
||||
// 设置频道卡的所有者UUID(如果有的话)
|
||||
eap$link.setPlacerId(ownerUUID);
|
||||
eap$link.setFrequency(channel);
|
||||
eap$link.updateStatus();
|
||||
Logger.EAP$LOGGER.debug("[服务端] IOBus 设置频道: {}, 连接状态: {}", channel, eap$link.isConnected());
|
||||
|
|
|
|||
|
|
@ -69,10 +69,12 @@ public abstract class StorageBusPartChannelCardMixin implements IInterfaceWirele
|
|||
try {
|
||||
IUpgradeInventory inv = this.getUpgrades();
|
||||
long channel = 0L;
|
||||
java.util.UUID ownerUUID = null;
|
||||
boolean found = false;
|
||||
for (var stack : inv) {
|
||||
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
|
||||
channel = ChannelCardItem.getChannel(stack);
|
||||
ownerUUID = ChannelCardItem.getOwnerUUID(stack);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -106,6 +108,8 @@ public abstract class StorageBusPartChannelCardMixin implements IInterfaceWirele
|
|||
Logger.EAP$LOGGER.debug("[服务端] StorageBus 创建新的无线链接");
|
||||
}
|
||||
|
||||
// 设置频道卡的所有者UUID(如果有的话)
|
||||
eap$link.setPlacerId(ownerUUID);
|
||||
eap$link.setFrequency(channel);
|
||||
eap$link.updateStatus();
|
||||
Logger.EAP$LOGGER.debug("[服务端] StorageBus 设置频道: {}, 连接状态: {}", channel, eap$link.isConnected());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
package com.extendedae_plus.network;
|
||||
|
||||
import com.extendedae_plus.ae.items.ChannelCardItem;
|
||||
import com.extendedae_plus.init.ModItems;
|
||||
import com.extendedae_plus.util.WirelessTeamUtil;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 频道卡绑定网络包
|
||||
* 客户端发送到服务端,用于处理左键空气的绑定/解绑操作
|
||||
*/
|
||||
public class ChannelCardBindPacket {
|
||||
|
||||
private final InteractionHand hand;
|
||||
|
||||
public ChannelCardBindPacket(InteractionHand hand) {
|
||||
this.hand = hand;
|
||||
}
|
||||
|
||||
public static void encode(ChannelCardBindPacket packet, FriendlyByteBuf buf) {
|
||||
buf.writeEnum(packet.hand);
|
||||
}
|
||||
|
||||
public static ChannelCardBindPacket decode(FriendlyByteBuf buf) {
|
||||
return new ChannelCardBindPacket(buf.readEnum(InteractionHand.class));
|
||||
}
|
||||
|
||||
public static void handle(ChannelCardBindPacket packet, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ServerPlayer player = ctx.get().getSender();
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack stack = player.getItemInHand(packet.hand);
|
||||
if (stack.getItem() != ModItems.CHANNEL_CARD.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ServerLevel level = player.serverLevel();
|
||||
UUID currentOwner = ChannelCardItem.getOwnerUUID(stack);
|
||||
|
||||
if (currentOwner != null) {
|
||||
// 已有所有者,清除
|
||||
ChannelCardItem.clearOwner(stack);
|
||||
player.displayClientMessage(
|
||||
Component.translatable("item.extendedae_plus.channel_card.owner.cleared"),
|
||||
true
|
||||
);
|
||||
} else {
|
||||
// 写入当前玩家的UUID和团队信息
|
||||
UUID playerUUID = player.getUUID();
|
||||
ChannelCardItem.setOwnerUUID(stack, playerUUID);
|
||||
|
||||
// 获取团队名称用于显示
|
||||
Component teamName = WirelessTeamUtil.getNetworkOwnerName(level, playerUUID);
|
||||
ChannelCardItem.setTeamName(stack, teamName.getString());
|
||||
|
||||
player.displayClientMessage(
|
||||
Component.translatable("item.extendedae_plus.channel_card.owner.bound", teamName),
|
||||
true
|
||||
);
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
|
||||
221
src/main/java/com/extendedae_plus/util/WirelessTeamUtil.java
Normal file
221
src/main/java/com/extendedae_plus/util/WirelessTeamUtil.java
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
package com.extendedae_plus.util;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 无线收发器队伍工具类
|
||||
* 实现FTBTeams软依赖:有FTBTeams时使用队伍UUID,没有时使用玩家UUID
|
||||
*/
|
||||
public class WirelessTeamUtil {
|
||||
|
||||
private static final boolean FTB_TEAMS_LOADED = ModList.get().isLoaded("ftbteams");
|
||||
|
||||
/**
|
||||
* 获取用于无线网络隔离的UUID
|
||||
* - 如果安装了FTBTeams且玩家在队伍中,返回队伍UUID(同队玩家共享)
|
||||
* - 否则返回玩家自己的UUID(独立网络)
|
||||
*
|
||||
* @param level 服务端世界
|
||||
* @param playerUUID 玩家UUID
|
||||
* @return 网络所有者UUID
|
||||
*/
|
||||
public static UUID getNetworkOwnerUUID(@Nullable ServerLevel level, UUID playerUUID) {
|
||||
if (playerUUID == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!FTB_TEAMS_LOADED) {
|
||||
return playerUUID;
|
||||
}
|
||||
|
||||
if (level == null) {
|
||||
return playerUUID;
|
||||
}
|
||||
|
||||
try {
|
||||
return getTeamUUID(level, playerUUID);
|
||||
} catch (Exception e) {
|
||||
// 如果FTBTeams API调用失败,回退到玩家UUID
|
||||
return playerUUID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取网络所有者的显示名称(用于UI显示)
|
||||
*
|
||||
* @param level 服务端世界
|
||||
* @param playerUUID 玩家UUID
|
||||
* @return 显示名称
|
||||
*/
|
||||
public static Component getNetworkOwnerName(@Nullable ServerLevel level, UUID playerUUID) {
|
||||
if (FTB_TEAMS_LOADED && level != null) {
|
||||
try {
|
||||
return getTeamName(level, playerUUID);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试获取玩家名称
|
||||
if (level != null) {
|
||||
ServerPlayer player = level.getServer().getPlayerList().getPlayer(playerUUID);
|
||||
if (player != null) {
|
||||
return player.getName();
|
||||
}
|
||||
}
|
||||
|
||||
return Component.literal(playerUUID.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查网络所有者是否有效(玩家在线或队伍存在)
|
||||
*
|
||||
* @param level 服务端世界
|
||||
* @param playerUUID 玩家UUID
|
||||
* @return 是否有效
|
||||
*/
|
||||
public static boolean hasNetworkOwner(@Nullable ServerLevel level, UUID playerUUID) {
|
||||
if (FTB_TEAMS_LOADED && level != null) {
|
||||
try {
|
||||
return hasTeamOwner(level, playerUUID);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
// 检查玩家是否在线
|
||||
if (level != null) {
|
||||
return level.getServer().getPlayerList().getPlayer(playerUUID) != null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ==================== FTBTeams 集成(通过反射调用避免硬依赖)====================
|
||||
|
||||
private static UUID getTeamUUID(ServerLevel level, UUID playerUUID) {
|
||||
try {
|
||||
// 使用FTBTeams API
|
||||
var apiClass = Class.forName("dev.ftb.mods.ftbteams.api.FTBTeamsAPI");
|
||||
var api = apiClass.getMethod("api").invoke(null); // 静态方法,返回API实例
|
||||
|
||||
// 检查Manager是否已加载(在api实例上调用)
|
||||
Boolean isLoaded = (Boolean) api.getClass().getMethod("isManagerLoaded").invoke(api);
|
||||
|
||||
if (!isLoaded) {
|
||||
return playerUUID;
|
||||
}
|
||||
|
||||
var getManager = api.getClass().getMethod("getManager").invoke(api);
|
||||
|
||||
if (getManager == null) {
|
||||
return playerUUID;
|
||||
}
|
||||
|
||||
var managerClass = getManager.getClass();
|
||||
var getTeamForPlayer = managerClass.getMethod("getTeamForPlayerID", UUID.class);
|
||||
var teamOptional = getTeamForPlayer.invoke(getManager, playerUUID);
|
||||
|
||||
if (teamOptional != null) {
|
||||
var optionalClass = teamOptional.getClass();
|
||||
var isPresent = (boolean) optionalClass.getMethod("isPresent").invoke(teamOptional);
|
||||
|
||||
if (isPresent) {
|
||||
var team = optionalClass.getMethod("get").invoke(teamOptional);
|
||||
var teamClass = team.getClass();
|
||||
return (UUID) teamClass.getMethod("getTeamId").invoke(team);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 反射调用失败,回退
|
||||
}
|
||||
|
||||
return playerUUID;
|
||||
}
|
||||
|
||||
private static Component getTeamName(ServerLevel level, UUID playerUUID) {
|
||||
try {
|
||||
var apiClass = Class.forName("dev.ftb.mods.ftbteams.api.FTBTeamsAPI");
|
||||
var api = apiClass.getMethod("api").invoke(null);
|
||||
|
||||
// 检查Manager是否已加载
|
||||
Boolean isLoaded = (Boolean) api.getClass().getMethod("isManagerLoaded").invoke(api);
|
||||
if (!isLoaded) {
|
||||
// Manager未加载,回退到玩家名称
|
||||
ServerPlayer player = level.getServer().getPlayerList().getPlayer(playerUUID);
|
||||
if (player != null) {
|
||||
return player.getName();
|
||||
}
|
||||
return Component.literal(playerUUID.toString());
|
||||
}
|
||||
|
||||
var getManager = api.getClass().getMethod("getManager").invoke(api);
|
||||
|
||||
if (getManager == null) {
|
||||
return Component.literal(playerUUID.toString());
|
||||
}
|
||||
|
||||
var managerClass = getManager.getClass();
|
||||
var getTeamForPlayer = managerClass.getMethod("getTeamForPlayerID", UUID.class);
|
||||
var teamOptional = getTeamForPlayer.invoke(getManager, playerUUID);
|
||||
|
||||
if (teamOptional != null) {
|
||||
var optionalClass = teamOptional.getClass();
|
||||
var isPresent = (boolean) optionalClass.getMethod("isPresent").invoke(teamOptional);
|
||||
|
||||
if (isPresent) {
|
||||
var team = optionalClass.getMethod("get").invoke(teamOptional);
|
||||
var teamClass = team.getClass();
|
||||
return (Component) teamClass.getMethod("getName").invoke(team);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 反射调用失败,回退
|
||||
}
|
||||
|
||||
// 回退到玩家名称
|
||||
ServerPlayer player = level.getServer().getPlayerList().getPlayer(playerUUID);
|
||||
if (player != null) {
|
||||
return player.getName();
|
||||
}
|
||||
|
||||
return Component.literal(playerUUID.toString());
|
||||
}
|
||||
|
||||
private static boolean hasTeamOwner(ServerLevel level, UUID playerUUID) {
|
||||
try {
|
||||
var apiClass = Class.forName("dev.ftb.mods.ftbteams.api.FTBTeamsAPI");
|
||||
var api = apiClass.getMethod("api").invoke(null);
|
||||
|
||||
// 检查Manager是否已加载
|
||||
Boolean isLoaded = (Boolean) api.getClass().getMethod("isManagerLoaded").invoke(api);
|
||||
if (!isLoaded) {
|
||||
return level.getServer().getPlayerList().getPlayer(playerUUID) != null;
|
||||
}
|
||||
|
||||
var getManager = api.getClass().getMethod("getManager").invoke(api);
|
||||
|
||||
if (getManager == null) {
|
||||
return level.getServer().getPlayerList().getPlayer(playerUUID) != null;
|
||||
}
|
||||
|
||||
var managerClass = getManager.getClass();
|
||||
var getTeamForPlayer = managerClass.getMethod("getTeamForPlayerID", UUID.class);
|
||||
var teamOptional = getTeamForPlayer.invoke(getManager, playerUUID);
|
||||
|
||||
if (teamOptional != null) {
|
||||
var optionalClass = teamOptional.getClass();
|
||||
return (boolean) optionalClass.getMethod("isPresent").invoke(teamOptional);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 反射调用失败,回退
|
||||
}
|
||||
|
||||
return level.getServer().getPlayerList().getPlayer(playerUUID) != null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -103,6 +103,11 @@
|
|||
"item.extendedae_plus.channel_card.channel": "Frequency: %s",
|
||||
"item.extendedae_plus.channel_card.channel.unset": "Frequency: Unset",
|
||||
"item.extendedae_plus.channel_card.set": "Frequency set to: %s",
|
||||
"item.extendedae_plus.channel_card.owner.unset": "Owner: Unbound",
|
||||
"item.extendedae_plus.channel_card.owner.team": "Owner: %s",
|
||||
"item.extendedae_plus.channel_card.owner.player": "Owner: Player %s",
|
||||
"item.extendedae_plus.channel_card.owner.bound": "Bound to: %s",
|
||||
"item.extendedae_plus.channel_card.owner.cleared": "Owner binding cleared",
|
||||
"group.pattern_provider.name": "Pattern Provider",
|
||||
"group.entity_ticker.name": "Entity Accelerator",
|
||||
"group.storage.name": "StorageBus"
|
||||
|
|
|
|||
|
|
@ -104,6 +104,11 @@
|
|||
"item.extendedae_plus.channel_card.channel": "频率:%s",
|
||||
"item.extendedae_plus.channel_card.channel.unset": "频率:未设置",
|
||||
"item.extendedae_plus.channel_card.set": "已设置频率:%s",
|
||||
"item.extendedae_plus.channel_card.owner.unset": "所有者:未绑定",
|
||||
"item.extendedae_plus.channel_card.owner.team": "所有者:%s",
|
||||
"item.extendedae_plus.channel_card.owner.player": "所有者:玩家 %s",
|
||||
"item.extendedae_plus.channel_card.owner.bound": "已绑定至:%s",
|
||||
"item.extendedae_plus.channel_card.owner.cleared": "已清除所有者绑定",
|
||||
"group.pattern_provider.name": "样板供应器",
|
||||
"group.entity_ticker.name": "实体加速器",
|
||||
"group.storage.name": "存储总线"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user