标签无线收发器基本完成

This commit is contained in:
GaLicn 2025-12-12 14:22:27 +08:00
parent 7359d49dec
commit d5b7c09ac9
7 changed files with 124 additions and 103 deletions

View File

@ -9,8 +9,8 @@ import com.mojang.blaze3d.systems.RenderSystem;
import net.neoforged.neoforge.network.PacketDistributor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.ImageButton;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
@ -42,10 +42,10 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
private static final int INFO_MAX_WIDTH = 116; // 信息区实际宽度(249-134+1=116)
private EditBox searchBox;
private ImageButton newBtn;
private ImageButton deleteBtn;
private ImageButton setBtn;
private ImageButton disconnectBtn;
private Button newBtn;
private Button deleteBtn;
private Button setBtn;
private Button disconnectBtn;
private final BlockPos bePos;
private final List<LabelEntry> entries = new ArrayList<>();
@ -90,14 +90,14 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
int secondColX = startX + BTN_W + hGap;
int secondRowY = startY + BTN_H + vGap;
this.newBtn = new StateImageButton(startX, startY, BTN_W, BTN_H, BTN_U, BTN_V, 2, 177, 2, 195, TEX, TEX_W, TEX_H,
b -> sendSet(searchBox.getValue()), Component.translatable("gui.extendedae_plus.labeled_wireless.button.new"));
this.deleteBtn = new StateImageButton(secondColX, startY, BTN_W, BTN_H, BTN_U, BTN_V, 2, 177, 2, 195, TEX, TEX_W, TEX_H,
b -> sendDelete(), Component.translatable("gui.extendedae_plus.labeled_wireless.button.delete"));
this.setBtn = new StateImageButton(startX, secondRowY, BTN_W, BTN_H, BTN_U, BTN_V, 2, 177, 2, 195, TEX, TEX_W, TEX_H,
b -> sendSet(getSelectedLabel()), Component.translatable("gui.extendedae_plus.labeled_wireless.button.set"));
this.disconnectBtn = new StateImageButton(secondColX, secondRowY, BTN_W, BTN_H, BTN_U, BTN_V, 2, 177, 2, 195, TEX, TEX_W, TEX_H,
b -> sendDisconnect(), Component.translatable("gui.extendedae_plus.labeled_wireless.button.refresh"));
this.newBtn = Button.builder(Component.translatable("gui.extendedae_plus.labeled_wireless.button.new"), b -> sendSet(searchBox.getValue()))
.bounds(startX, startY, BTN_W, BTN_H).build();
this.deleteBtn = Button.builder(Component.translatable("gui.extendedae_plus.labeled_wireless.button.delete"), b -> sendDelete())
.bounds(secondColX, startY, BTN_W, BTN_H).build();
this.setBtn = Button.builder(Component.translatable("gui.extendedae_plus.labeled_wireless.button.set"), b -> sendSet(getSelectedLabel()))
.bounds(startX, secondRowY, BTN_W, BTN_H).build();
this.disconnectBtn = Button.builder(Component.translatable("gui.extendedae_plus.labeled_wireless.button.refresh"), b -> sendDisconnect())
.bounds(secondColX, secondRowY, BTN_W, BTN_H).build();
this.addRenderableWidget(this.newBtn);
this.addRenderableWidget(this.deleteBtn);
@ -109,6 +109,7 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
@Override
public void render(GuiGraphics gfx, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(gfx, mouseX, mouseY, partialTicks);
super.render(gfx, mouseX, mouseY, partialTicks);
drawAllButtonText(gfx);
this.renderTooltip(gfx, mouseX, mouseY);
@ -183,13 +184,13 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double scrollDeltaX, double scrollDeltaY) {
public boolean mouseScrolled(double mouseX, double mouseY, double scrollDelta, double scrollDeltaY) {
if (isMouseInList(mouseX, mouseY) || isMouseInScrollbar(mouseX, mouseY)) {
int maxOffset = Math.max(0, filtered.size() - VISIBLE_ROWS);
scrollOffset = Math.max(0, Math.min(maxOffset, scrollOffset - (int) Math.signum(scrollDeltaY)));
return true;
}
return super.mouseScrolled(mouseX, mouseY, scrollDeltaX, scrollDeltaY);
return super.mouseScrolled(mouseX, mouseY, scrollDelta, scrollDeltaY);
}
private void renderList(GuiGraphics gfx) {
@ -290,12 +291,12 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
}
private void requestList() {
ModNetwork.CHANNEL.sendToServer(new LabelNetworkListC2SPacket(bePos));
PacketDistributor.sendToServer(new LabelNetworkListC2SPacket(bePos));
}
private void sendSet(String label) {
if (label == null) label = "";
ModNetwork.CHANNEL.sendToServer(new LabelNetworkActionC2SPacket(bePos, label, LabelNetworkActionC2SPacket.Action.SET));
PacketDistributor.sendToServer(new LabelNetworkActionC2SPacket(bePos, label, LabelNetworkActionC2SPacket.Action.SET));
this.lastSelectedLabel = label;
this.searchBox.setValue("");
requestList();
@ -307,13 +308,13 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
label = searchBox.getValue();
}
if (label == null) label = "";
ModNetwork.CHANNEL.sendToServer(new LabelNetworkActionC2SPacket(bePos, label, LabelNetworkActionC2SPacket.Action.DELETE));
PacketDistributor.sendToServer(new LabelNetworkActionC2SPacket(bePos, label, LabelNetworkActionC2SPacket.Action.DELETE));
this.lastSelectedLabel = "";
requestList();
}
private void sendDisconnect() {
ModNetwork.CHANNEL.sendToServer(new LabelNetworkActionC2SPacket(bePos, "", LabelNetworkActionC2SPacket.Action.DISCONNECT));
PacketDistributor.sendToServer(new LabelNetworkActionC2SPacket(bePos, "", LabelNetworkActionC2SPacket.Action.DISCONNECT));
this.lastSelectedLabel = "";
requestList();
}
@ -353,27 +354,7 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
private record LabelEntry(String label, long channel) {}
private void drawAllButtonText(GuiGraphics gfx) {
// 按钮文本24px 内居中避免溢出放在 super.render 之后确保绘制在按钮纹理之上
int startX = this.leftPos + 145;
int startY = this.topPos + 101;
int hGap = 30;
int vGap = 8;
int secondColX = startX + BTN_W + hGap;
int secondRowY = startY + BTN_H + vGap;
drawButtonText(gfx, Component.translatable("gui.extendedae_plus.labeled_wireless.button.new"), startX, startY);
drawButtonText(gfx, Component.translatable("gui.extendedae_plus.labeled_wireless.button.delete"), secondColX, startY);
drawButtonText(gfx, Component.translatable("gui.extendedae_plus.labeled_wireless.button.set"), startX, secondRowY);
drawButtonText(gfx, Component.translatable("gui.extendedae_plus.labeled_wireless.button.refresh"), secondColX, secondRowY);
}
private void drawButtonText(GuiGraphics gfx, Component text, int x, int y) {
String s = this.font.plainSubstrByWidth(text.getString(), BTN_W - 4);
int tx = x + (BTN_W - this.font.width(s)) / 2;
int ty = y + (BTN_H - this.font.lineHeight) / 2 + 1;
gfx.drawString(this.font, s, tx, ty, 0xFFFFFF, false);
}
private void drawAllButtonText(GuiGraphics gfx) {}
private void ensureSelectionVisible() {
if (selectedIndex < 0) return;
@ -416,60 +397,4 @@ public class LabeledWirelessTransceiverScreen extends AbstractContainerScreen<La
return isEnglish() ? 0.75f : 1.0f;
}
private static class StateImageButton extends ImageButton {
private final ResourceLocation tex;
private final int texW;
private final int texH;
private final int baseU;
private final int baseV;
private final int hoverU;
private final int hoverV;
private final int pressU;
private final int pressV;
private boolean pressedVisual = false;
public StateImageButton(int x, int y, int w, int h, int baseU, int baseV, int hoverU, int hoverV, int pressU, int pressV,
ResourceLocation tex, int texW, int texH, OnPress onPress, Component tooltip) {
super(x, y, w, h, baseU, baseV, 0, tex, texW, texH, onPress, tooltip);
this.tex = tex;
this.texW = texW;
this.texH = texH;
this.baseU = baseU;
this.baseV = baseV;
this.hoverU = hoverU;
this.hoverV = hoverV;
this.pressU = pressU;
this.pressV = pressV;
}
@Override
public void renderWidget(GuiGraphics gfx, int mouseX, int mouseY, float partialTicks) {
boolean hovered = this.isMouseOver(mouseX, mouseY);
boolean pressed = pressedVisual || (hovered && GLFW.glfwGetMouseButton(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_MOUSE_BUTTON_1) == GLFW.GLFW_PRESS);
int u = baseU;
int v = baseV;
if (pressed) {
u = pressU;
v = pressV;
} else if (hovered) {
u = hoverU;
v = hoverV;
}
gfx.blit(tex, this.getX(), this.getY(), u, v, this.width, this.height, texW, texH);
}
@Override
public void onClick(double mouseX, double mouseY) {
this.pressedVisual = true;
super.onClick(mouseX, mouseY);
this.setFocused(false);
}
@Override
public void onRelease(double mouseX, double mouseY) {
this.pressedVisual = false;
super.onRelease(mouseX, mouseY);
this.setFocused(false);
}
}
}

View File

@ -1,6 +1,7 @@
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.ItemInteractionResult;
@ -16,6 +17,8 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
import com.extendedae_plus.init.ModBlockEntities;
@ -58,6 +61,17 @@ public class LabeledWirelessTransceiverBlock extends Block implements EntityBloc
: null;
}
@Override
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 LabeledWirelessTransceiverBlockEntity te) {
te.setPlacerId(player.getUUID(), player.getName().getString());
}
}
}
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hit) {
if (level.isClientSide) {
@ -67,7 +81,9 @@ public class LabeledWirelessTransceiverBlock extends Block implements EntityBloc
if (!(be instanceof LabeledWirelessTransceiverBlockEntity te)) {
return InteractionResult.PASS;
}
player.openMenu(te, pos);
if (player instanceof ServerPlayer sp) {
sp.openMenu(te, pos);
}
return InteractionResult.CONSUME;
}

View File

@ -21,9 +21,12 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.MenuProvider;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
@ -111,6 +114,14 @@ public class LabeledWirelessTransceiverBlockEntity extends AEBaseBlockEntity imp
return placerName;
}
public void setPlacerIdFrom(ItemStack stack, @Nullable LivingEntity placer) {
if (placer instanceof Player player) {
this.setPlacerId(player.getUUID(), player.getName().getString());
} else if (stack.has(DataComponents.CUSTOM_NAME)) {
this.setPlacerId(null, stack.getHoverName().getString());
}
}
public long getFrequency() {
return frequency;
}

View File

@ -17,6 +17,12 @@ public final class ModCapabilities {
ModBlockEntities.WIRELESS_TRANSCEIVER_BE.get(),
(be, ctx) -> (IInWorldGridNodeHost) be
);
// 标签无线收发器
event.registerBlockEntity(
AECapabilities.IN_WORLD_GRID_NODE_HOST,
ModBlockEntities.LABELED_WIRELESS_TRANSCEIVER_BE.get(),
(be, ctx) -> (IInWorldGridNodeHost) be
);
// 供应器状态控制器实现了 IInWorldGridNodeHost
event.registerBlockEntity(

View File

@ -0,0 +1,65 @@
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") : "";
tooltip.add(Component.translatable("extendedae_plus.jade.label", label.isEmpty() ? "-" : label));
// 所有者
if (data.contains("ownerName")) {
tooltip.add(Component.translatable("extendedae_plus.jade.owner", data.getString("ownerName")));
} else if (data.contains("placerId")) {
java.util.UUID placerId = data.getUUID("placerId");
tooltip.add(Component.translatable("extendedae_plus.jade.owner", placerId.toString().substring(0, 8) + "..."));
} else {
tooltip.add(Component.translatable("extendedae_plus.jade.owner.public"));
}
// 频道占用
if (data.contains("usedChannels") && data.contains("maxChannels")) {
int used = data.getInt("usedChannels");
int max = data.getInt("maxChannels");
if (max <= 0) {
tooltip.add(Component.translatable("extendedae_plus.jade.channels", used));
} else {
tooltip.add(Component.translatable("extendedae_plus.jade.channels_of", used, max));
}
}
// 网络在线
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 = ResourceLocation.fromNamespaceAndPath("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);
}

View File

@ -34,9 +34,8 @@ public record LabelNetworkActionC2SPacket(BlockPos pos, String label, Action act
public static void handle(LabelNetworkActionC2SPacket packet, IPayloadContext ctx) {
ctx.enqueueWork(() -> {
var player = ctx.player();
if (player == null) return;
var level = (net.minecraft.server.level.ServerLevel) player.level();
if (!(ctx.player() instanceof net.minecraft.server.level.ServerPlayer player)) return;
var level = player.serverLevel();
if (!level.hasChunkAt(packet.pos)) return;
var be = level.getBlockEntity(packet.pos);
if (!(be instanceof LabeledWirelessTransceiverBlockEntity te)) return;

View File

@ -31,9 +31,8 @@ public record LabelNetworkListC2SPacket(BlockPos pos) implements CustomPacketPay
public static void handle(LabelNetworkListC2SPacket pkt, IPayloadContext ctx) {
ctx.enqueueWork(() -> {
var player = ctx.player();
if (player == null) return;
var level = (net.minecraft.server.level.ServerLevel) player.level();
if (!(ctx.player() instanceof net.minecraft.server.level.ServerPlayer player)) return;
var level = player.serverLevel();
if (!level.hasChunkAt(pkt.pos)) return;
var be = level.getBlockEntity(pkt.pos);
if (!(be instanceof LabeledWirelessTransceiverBlockEntity te)) return;