基础功能
This commit is contained in:
parent
0b4443773d
commit
044a0c39f7
|
|
@ -105,24 +105,17 @@ public class LabelNetworkRegistry extends SavedData {
|
|||
}
|
||||
|
||||
/**
|
||||
* 注销端点;若网络无端点则清理。
|
||||
* 注销端点;不再自动删除网络,网络的移除需显式调用 removeNetwork。
|
||||
*/
|
||||
public synchronized void unregister(IWirelessEndpoint endpoint) {
|
||||
ServerLevel level = endpoint.getServerLevel();
|
||||
if (level == null) return;
|
||||
ResourceKey<Level> dimKey = ModConfig.INSTANCE.wirelessCrossDimEnable ? null : level.dimension();
|
||||
BlockPos pos = endpoint.getBlockPos();
|
||||
Iterator<Map.Entry<Key, LabelNetwork>> it = networks.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
var entry = it.next();
|
||||
LabelNetwork net = entry.getValue();
|
||||
for (LabelNetwork net : networks.values()) {
|
||||
net.endpoints.removeIf(ref -> ref.matches(dimKey, pos));
|
||||
if (net.endpoints.isEmpty()) {
|
||||
net.destroyVirtualNode();
|
||||
it.remove();
|
||||
setDirty();
|
||||
}
|
||||
}
|
||||
setDirty();
|
||||
}
|
||||
|
||||
public synchronized LabelNetwork getNetwork(ServerLevel level, String rawLabel, @Nullable UUID placerId) {
|
||||
|
|
@ -134,6 +127,24 @@ public class LabelNetworkRegistry extends SavedData {
|
|||
return networks.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显式删除一个网络(销毁虚拟节点),仅在 UI “删除” 时调用。
|
||||
*/
|
||||
public synchronized boolean removeNetwork(ServerLevel level, String rawLabel, @Nullable UUID placerId) {
|
||||
String label = normalizeLabel(rawLabel);
|
||||
if (label == null) return false;
|
||||
UUID owner = placerId == null ? WirelessMasterRegistry.PUBLIC_NETWORK_UUID : WirelessTeamUtil.getNetworkOwnerUUID(level, placerId);
|
||||
ResourceKey<Level> dimKey = ModConfig.INSTANCE.wirelessCrossDimEnable ? null : level.dimension();
|
||||
Key key = new Key(dimKey, label, owner);
|
||||
LabelNetwork net = networks.remove(key);
|
||||
if (net != null) {
|
||||
net.destroyVirtualNode();
|
||||
setDirty();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前玩家所属网络列表(按标签排序)。
|
||||
*/
|
||||
|
|
@ -147,7 +158,7 @@ public class LabelNetworkRegistry extends SavedData {
|
|||
if (!Objects.equals(key.dim(), dimKey)) continue;
|
||||
list.add(new LabelNetworkSnapshot(key.label(), entry.getValue().channel()));
|
||||
}
|
||||
list.sort(Comparator.comparing(LabelNetworkSnapshot::label));
|
||||
list.sort(Comparator.comparingLong(LabelNetworkSnapshot::channel));
|
||||
return list;
|
||||
}
|
||||
|
||||
|
|
@ -190,7 +201,12 @@ public class LabelNetworkRegistry extends SavedData {
|
|||
}
|
||||
|
||||
private long allocateChannel() {
|
||||
return nextChannel++;
|
||||
// 全局递增,不复用历史频道,从 1_000_000 起
|
||||
if (nextChannel < CHANNEL_START) {
|
||||
nextChannel = CHANNEL_START;
|
||||
}
|
||||
long ch = nextChannel++;
|
||||
return ch;
|
||||
}
|
||||
|
||||
/* 内部类型 */
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
|
|||
private final List<LabelEntry> filtered = new ArrayList<>();
|
||||
private int scrollOffset = 0;
|
||||
private int selectedIndex = -1;
|
||||
private String lastSelectedLabel = "";
|
||||
private String currentLabel = "";
|
||||
private long currentChannel = 0L;
|
||||
|
||||
|
|
@ -153,6 +154,7 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
|
|||
int idx = scrollOffset + row;
|
||||
if (idx >= 0 && idx < filtered.size()) {
|
||||
selectedIndex = idx;
|
||||
lastSelectedLabel = filtered.get(idx).label();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -245,6 +247,7 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
|
|||
}
|
||||
|
||||
private void applyFilter() {
|
||||
String prevSelected = lastSelectedLabel;
|
||||
String q = searchBox.getValue() == null ? "" : searchBox.getValue().trim().toLowerCase();
|
||||
filtered.clear();
|
||||
if (q.isEmpty()) {
|
||||
|
|
@ -257,7 +260,16 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
|
|||
}
|
||||
}
|
||||
scrollOffset = 0;
|
||||
selectedIndex = filtered.isEmpty() ? -1 : Math.min(selectedIndex, filtered.size() - 1);
|
||||
selectedIndex = -1;
|
||||
if (prevSelected != null && !prevSelected.isEmpty()) {
|
||||
for (int i = 0; i < filtered.size(); i++) {
|
||||
if (filtered.get(i).label().equals(prevSelected)) {
|
||||
selectedIndex = i;
|
||||
ensureSelectionVisible();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void requestList() {
|
||||
|
|
@ -267,6 +279,8 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
|
|||
private void sendSet(String label) {
|
||||
if (label == null) label = "";
|
||||
ModNetwork.CHANNEL.sendToServer(new LabelNetworkActionC2SPacket(bePos, label, LabelNetworkActionC2SPacket.Action.SET));
|
||||
this.lastSelectedLabel = label;
|
||||
this.searchBox.setValue("");
|
||||
requestList();
|
||||
}
|
||||
|
||||
|
|
@ -277,11 +291,13 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
|
|||
}
|
||||
if (label == null) label = "";
|
||||
ModNetwork.CHANNEL.sendToServer(new LabelNetworkActionC2SPacket(bePos, label, LabelNetworkActionC2SPacket.Action.DELETE));
|
||||
this.lastSelectedLabel = "";
|
||||
requestList();
|
||||
}
|
||||
|
||||
private void sendDisconnect() {
|
||||
ModNetwork.CHANNEL.sendToServer(new LabelNetworkActionC2SPacket(bePos, "", LabelNetworkActionC2SPacket.Action.DISCONNECT));
|
||||
this.lastSelectedLabel = "";
|
||||
requestList();
|
||||
}
|
||||
|
||||
|
|
@ -293,12 +309,20 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
|
|||
}
|
||||
|
||||
public void updateList(List<LabelNetworkRegistry.LabelNetworkSnapshot> list, String currentLabel, long currentChannel) {
|
||||
String prevSelected = getSelectedLabel();
|
||||
this.entries.clear();
|
||||
for (LabelNetworkRegistry.LabelNetworkSnapshot s : list) {
|
||||
this.entries.add(new LabelEntry(s.label(), s.channel()));
|
||||
}
|
||||
this.currentLabel = currentLabel == null ? "" : currentLabel;
|
||||
this.currentChannel = currentChannel;
|
||||
if (prevSelected != null && !prevSelected.isEmpty()) {
|
||||
this.lastSelectedLabel = prevSelected;
|
||||
} else if (this.currentLabel != null && !this.currentLabel.isEmpty()) {
|
||||
this.lastSelectedLabel = this.currentLabel;
|
||||
} else {
|
||||
this.lastSelectedLabel = "";
|
||||
}
|
||||
applyFilter();
|
||||
}
|
||||
|
||||
|
|
@ -329,4 +353,15 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
|
|||
int ty = y + (BTN_H - this.font.lineHeight) / 2 + 1;
|
||||
gfx.drawString(this.font, s, tx, ty, 0xFFFFFF, false);
|
||||
}
|
||||
|
||||
private void ensureSelectionVisible() {
|
||||
if (selectedIndex < 0) return;
|
||||
int maxOffset = Math.max(0, filtered.size() - VISIBLE_ROWS);
|
||||
int targetRow = selectedIndex;
|
||||
if (targetRow < scrollOffset) {
|
||||
scrollOffset = targetRow;
|
||||
} else if (targetRow >= scrollOffset + VISIBLE_ROWS) {
|
||||
scrollOffset = Math.min(maxOffset, targetRow - VISIBLE_ROWS + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
package com.extendedae_plus.integration.jade;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import snownee.jade.api.BlockAccessor;
|
||||
import snownee.jade.api.IBlockComponentProvider;
|
||||
import snownee.jade.api.ITooltip;
|
||||
import snownee.jade.api.config.IPluginConfig;
|
||||
|
||||
public enum LabeledWirelessTransceiverComponents implements IBlockComponentProvider {
|
||||
LABEL_AND_CHANNEL("labeled_wireless_component") {
|
||||
@Override
|
||||
protected void add(BlockAccessor accessor, ITooltip tooltip, IPluginConfig config, net.minecraft.nbt.CompoundTag data) {
|
||||
String label = data.contains("label") ? data.getString("label") : "";
|
||||
long channel = data.contains("channel") ? data.getLong("channel") : 0L;
|
||||
tooltip.add(Component.translatable("extendedae_plus.jade.label", label.isEmpty() ? "-" : label));
|
||||
tooltip.add(Component.translatable("extendedae_plus.jade.frequency", channel));
|
||||
|
||||
if (data.contains("networkUsable")) {
|
||||
boolean online = data.getBoolean("networkUsable");
|
||||
tooltip.add(Component.translatable(online ? "extendedae_plus.jade.online" : "extendedae_plus.jade.offline"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final ResourceLocation uid;
|
||||
|
||||
LabeledWirelessTransceiverComponents(String name) {
|
||||
this.uid = new ResourceLocation("extendedae_plus", name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ITooltip tooltip, BlockAccessor accessor, IPluginConfig config) {
|
||||
if (accessor.getServerData() != null) {
|
||||
add(accessor, tooltip, config, accessor.getServerData());
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void add(BlockAccessor accessor, ITooltip tooltip, IPluginConfig config, net.minecraft.nbt.CompoundTag data);
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.extendedae_plus.integration.jade;
|
||||
|
||||
import appeng.api.networking.IGrid;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import com.extendedae_plus.content.wireless.LabeledWirelessTransceiverBlockEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import snownee.jade.api.BlockAccessor;
|
||||
import snownee.jade.api.IServerDataProvider;
|
||||
|
||||
/**
|
||||
* 标签无线收发器:服务端数据同步。
|
||||
* 仅包含标签名、频道、网络在线状态。
|
||||
*/
|
||||
public enum LabeledWirelessTransceiverProvider implements IServerDataProvider<BlockAccessor> {
|
||||
INSTANCE;
|
||||
|
||||
private static final ResourceLocation UID = new ResourceLocation("extendedae_plus", "labeled_wireless_info");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getUid() {
|
||||
return UID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendServerData(CompoundTag data, BlockAccessor accessor) {
|
||||
if (!(accessor.getBlockEntity() instanceof LabeledWirelessTransceiverBlockEntity be)) return;
|
||||
String label = be.getLabelForDisplay();
|
||||
if (label != null) {
|
||||
data.putString("label", label);
|
||||
}
|
||||
data.putLong("channel", be.getFrequency());
|
||||
|
||||
IGridNode node = be.getGridNode();
|
||||
IGrid grid = node == null ? null : node.getGrid();
|
||||
boolean networkUsable = false;
|
||||
if (grid != null) {
|
||||
try {
|
||||
networkUsable = grid.getEnergyService().isNetworkPowered();
|
||||
} catch (Throwable ignored) {
|
||||
networkUsable = false;
|
||||
}
|
||||
}
|
||||
data.putBoolean("networkUsable", networkUsable);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.extendedae_plus.integration.jade;
|
|||
|
||||
import com.extendedae_plus.content.wireless.WirelessTransceiverBlock;
|
||||
import com.extendedae_plus.content.wireless.WirelessTransceiverBlockEntity;
|
||||
import com.extendedae_plus.content.wireless.LabeledWirelessTransceiverBlock;
|
||||
import com.extendedae_plus.content.wireless.LabeledWirelessTransceiverBlockEntity;
|
||||
import snownee.jade.api.IWailaClientRegistration;
|
||||
import snownee.jade.api.IWailaCommonRegistration;
|
||||
import snownee.jade.api.IWailaPlugin;
|
||||
|
|
@ -14,6 +16,7 @@ public class WirelessTransceiverJadePlugin implements IWailaPlugin {
|
|||
public void register(IWailaCommonRegistration registration) {
|
||||
// 注册服务端数据提供者(用于同步数据)
|
||||
registration.registerBlockDataProvider(WirelessTransceiverProvider.INSTANCE, WirelessTransceiverBlockEntity.class);
|
||||
registration.registerBlockDataProvider(com.extendedae_plus.integration.jade.LabeledWirelessTransceiverProvider.INSTANCE, LabeledWirelessTransceiverBlockEntity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -22,5 +25,6 @@ public class WirelessTransceiverJadePlugin implements IWailaPlugin {
|
|||
for (var component : WirelessTransceiverJadePluginComponents.values()) {
|
||||
registration.registerBlockComponent(component, WirelessTransceiverBlock.class);
|
||||
}
|
||||
registration.registerBlockComponent(com.extendedae_plus.integration.jade.LabeledWirelessTransceiverComponents.LABEL_AND_CHANNEL, LabeledWirelessTransceiverBlock.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -52,7 +52,15 @@ public class LabelNetworkActionC2SPacket {
|
|||
|
||||
switch (packet.action) {
|
||||
case SET -> te.applyLabel(packet.label);
|
||||
case DELETE, DISCONNECT -> te.clearLabel();
|
||||
case DELETE -> {
|
||||
String target = packet.label == null || packet.label.isEmpty() ? te.getLabelForDisplay() : packet.label;
|
||||
if (target != null && !target.isEmpty()) {
|
||||
com.extendedae_plus.ae.wireless.LabelNetworkRegistry.get(level)
|
||||
.removeNetwork(level, target, te.getPlacerId());
|
||||
}
|
||||
te.clearLabel();
|
||||
}
|
||||
case DISCONNECT -> te.clearLabel();
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
|
|
|
|||
|
|
@ -215,10 +215,12 @@
|
|||
"extendedae_plus.jade.unlocked": "Unlocked",
|
||||
"extendedae_plus.jade.online": "Device Online",
|
||||
"extendedae_plus.jade.offline": "Device Offline",
|
||||
"extendedae_plus.jade.label": "Label: %s",
|
||||
"extendedae_plus.jade.channels": "Channels: %s",
|
||||
"extendedae_plus.jade.channels_of": "Channels: %s/%s",
|
||||
"extendedae_plus.jade.owner": "Owner: %s",
|
||||
"extendedae_plus.jade.owner.public": "Owner: Public",
|
||||
"config.jade.plugin_extendedae_plus.labeled_wireless_component": "Labeled Wireless Info",
|
||||
|
||||
"extendedae_plus.command.server_side_only": "This command must be run on server side",
|
||||
"extendedae_plus.command.storage_manager_not_initialized": "InfinityStorageManager is not initialized",
|
||||
|
|
|
|||
|
|
@ -214,10 +214,12 @@
|
|||
"extendedae_plus.jade.unlocked": "未锁定",
|
||||
"extendedae_plus.jade.online": "设备在线",
|
||||
"extendedae_plus.jade.offline": "设备离线",
|
||||
"extendedae_plus.jade.label": "标签: %s",
|
||||
"extendedae_plus.jade.channels": "频道: %s",
|
||||
"extendedae_plus.jade.channels_of": "频道: %s/%s",
|
||||
"extendedae_plus.jade.owner": "所有者: %s",
|
||||
"extendedae_plus.jade.owner.public": "所有者: 公共",
|
||||
"config.jade.plugin_extendedae_plus.labeled_wireless_component": "标签无线收发器信息",
|
||||
|
||||
"extendedae_plus.command.server_side_only": "此命令必须在服务器端执行",
|
||||
"extendedae_plus.command.storage_manager_not_initialized": "InfinityStorageManager未初始化",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user