public class BoxScreenHandler extends ScreenHandler { private final Inventory inventory; PropertyDelegate propertyDelegate; // 当服务器想要打开 screenHandler 时,客户端就会调用这个构造函数 // 客户端将调用父级构造函数,其中物品栏是空的。screenHandler 将自动将这个空的物品栏同步到服务器上 // 类似于物品栏,客户端将分配一个空的 propertyDelegate 并且它将自动与服务器同步 public BoxScreenHandler(int syncId, PlayerInventory playerInventory) { this(syncId, playerInventory, new SimpleInventory(9),new ArrayPropertyDelegate(1)); } // 该构造函数从服务器上的 BlockEntity 调用,服务器知道容器(Container)中的物品栏,因此可以直接将其作为参数提供。这个物品栏以及 propertyDelegate 将被同步到客户端 public BoxScreenHandler(int syncId, PlayerInventory playerInventory, Inventory inventory, PropertyDelegate propertyDelegate) { super(Test.BOX_SCREEN_HANDLER, syncId); checkSize(inventory, 9); this.inventory = inventory; this.propertyDelegate = propertyDelegate; // 有些物品栏会在玩家打开时作自定义逻辑操作(Custom Logic) inventory.onOpen(playerInventory.player); // 我们需要告诉 screenHandler 关于 propertyDelegate 里的数据,否则它不会同步这里面的数据 this.addProperties(propertyDelegate); // 这将会把物品槽(Slot)放在 3x3 网格中正确的位置,物品槽(Slot)在服务端和客户端都存在! [...] } // 我们为已同步的整型提供了 getter, 所以 Screen 可以访问它并且在屏幕上显示它。 public int getSyncedNumber(){ return propertyDelegate.get(0); } @Override public boolean canUse(PlayerEntity player) { return this.inventory.canPlayerUse(player); } @Override public ItemStack transferSlot(PlayerEntity player, int invSlot) {[...]} }