zh_cn:tutorial:extendedscreenhandler
This is an old revision of the document!
Table of Contents
使用扩展的 ScreenHandler 同步数据
在本教程中,我们将使用 ExtendedScreenHandler 在 ScreenHandler 打开时将任意数据从服务器传输到客户端 ScreenHandler。
在我们的示例中,我们将用方块的位置作为容器的标题。
方块实体
由于 Block 类根本不需要更改,我们将其留在这里。
我们的方块实体现在实现了 “ExtendedScreenHandlerFactory”,这个接口为我们提供了 “writeScreenOpeningData” 方法,当它请求客户端(client)打开一个 “ScreenHandler” 时,将在服务器(server)上调用该方法。 您写入 “PacketByteBuf” 的数据将通过网络传输到客户端(client)。
- BoxBlockEntity.java
- public class BoxBlockEntity extends BlockEntity implements ExtendedScreenHandlerFactory, ImplementedInventory {
- private final DefaultedList<ItemStack> inventory = DefaultedList.ofSize(9, ItemStack.EMPTY);
- public BoxBlockEntity() {
- super(Test.BOX_BLOCK_ENTITY);
- }
- //来自 ImplementedInventory 接口
- @Override
- public DefaultedList<ItemStack> getItems() {
- return inventory;
- }
- //这些方法来自 NamedScreenHandlerFactory 接口
- @Override
- public @Nullable ScreenHandler createMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player) {
- //我们将它提供给 screenHandler 作为我们的类实现 Inventory
- //一开始只有服务器(Server)有 Inventory ,这将在 ScreenHandler 中同步到客户端(Cilent)
- return new BoxScreenHandler(syncId, playerInventory, this);
- }
- @Override
- public Text getDisplayName() {
- return new TranslatableText(getCachedState().getBlock().getTranslationKey());
- }
- //此方法来自 ExtendedScreenHandlerFactory
- //当它请求客户端(client)打开 screenHandler 时,在服务器(server)上调用此方法
- //您写入 packetByteBuf 的内容将自动以(数据)包的形式传输到客户端
- //并在客户端(client)调用带有 packetByteBuf 参数的 ScreenHandler 构造函数
- //
- //您在此处插入内容的顺序与您需要提取它们的顺序相同。您不需要颠倒顺序!
- @Override
- public void writeScreenOpeningData(ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf) {
- //pos 字段是 BlockEntity 的公共字段
- packetByteBuf.writeBlockPos(pos);
- }
- }
新的 ExtendedScreenHandler (实例)
- BoxScreenHandler.java
- public class BoxScreenHandler extends ScreenHandler {
- //我们保存从服务器获得的 blockPos 并为其提供一个 getter,以便 BoxScreen 可以读取该信息
- private BlockPos pos;
- private final Inventory inventory;
- //当服务器(Server)希望它打开 screenHandler 时,在客户端(Cilent)上调用此构造函数,
- //客户端将使用一个空的 Inventory 调用超级构造函数,并且 screenHandler 将自动将此空库存与服务器上的库存同步。
- //新:客户端的构造函数现在获取我们在 BlockEntity 中填充的 PacketByteBuf
- public BoxScreenHandler(int syncId, PlayerInventory playerInventory, PacketByteBuf buf) {
- this(syncId, playerInventory, new SimpleInventory(9));
- pos = buf.readBlockPos();
- }
- //此构造函数从服务器上的 BlockEntity 调用,服务器知道容器的库存(你可以将它理解为物品栏),因此可以直接将其作为参数提供。 然后,此库存(物品栏)将同步到客户端。
- public BoxScreenHandler(int syncId, PlayerInventory playerInventory, Inventory inventory) {
- //[...]
- //有关其余代码,请参阅第一个 Screenhandler 教程
- //想一想,为什么我们在这里使用 BlockPos.ORIGIN?
- //This is because the packetByteBuf with our blockPosition is only availible on the Client, so we need a placeholder
- //value here. This is not a problem however, as the Server version of the ScreenHandler does not really need this
- //information.
- //(机翻警告)这是因为带有我们 blockPosition 的 packetByteBuf 仅在 Client 上可用,所以我们这里需要一个占位符值。 然而,这不是问题,
- //因为 ScreenHandler 的服务器版本并不真正需要此信息。
- pos = BlockPos.ORIGIN;
- [...]
- }
- //这个 getter 将被我们的 Screen 类使用
- public BlockPos getPos() {
- return pos;
- }
- @Override
- public boolean canUse(PlayerEntity player) {
- return this.inventory.canPlayerUse(player);
- }
- // 参阅 Screenhandler 教程
- // Shift + Player Inv Slot
- @Override
- public ItemStack transferSlot(PlayerEntity player, int invSlot);
- }
zh_cn/tutorial/extendedscreenhandler.1644499180.txt.gz · Last modified: 2022/02/10 13:19 by timothy_starman