public class BoxBlockEntity extends BlockEntity implements NamedScreenHandlerFactory, ImplementedInventory, Tickable { private final DefaultedList inventory = DefaultedList.ofSize(9, ItemStack.EMPTY); //this is the int we want to sync, it gets increased by one each tick private int syncedInt; //PropertyDelegate is an interface which we will implement inline here. //It can normally contain multiple integers as data identified by the index, but in this example we only have one. private final PropertyDelegate propertyDelegate = new PropertyDelegate() { @Override public int get(int index) { return syncedInt; } @Override public void set(int index, int value) { syncedInt = value; } //this is supposed to return the amount of integers you have in your delegate, in our example only one @Override public int size() { return 1; } }; public BoxBlockEntity() { super(Test.BOX_BLOCK_ENTITY); } //From the ImplementedInventory Interface @Override public DefaultedList getItems() { return inventory; } //These Methods are from the NamedScreenHandlerFactory Interface @Override public @Nullable ScreenHandler createMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player) { //We provide this to the screenHandler as our class Implements Inventory //Only the Server has the Inventory at the start, this will be synced to the client in the ScreenHandler //Similar to the inventory: The server has the PropertyDelegate and gives it to the server instance of the screen handler directly return new BoxScreenHandler(syncId, playerInventory, this,propertyDelegate); } @Override public Text getDisplayName() { // For versions 1.18.2 and below, please use return new TranslatableText(getCachedState().getBlock().getTranslationKey()); return Text.translatable(getCachedState().getBlock().getTranslationKey()); } //increase the synced Integer by one each tick, we only do this on the server for demonstration purposes. @Override public void tick() { if(!world.isClient) syncedInt++; } }