Skip to content

Synced properties

Juuz edited this page Jun 10, 2023 · 2 revisions

Synced int properties can be used to send an int value from the server to the client, for example a progress bar.

PropertyDelegates are used to hook screens up with the int data from another source, such as a block entity. In this tutorial, we'll implement PropertyDelegate for a simple machine block entity that has a progress field between 0 and 500.

Setting up the block entity

public class MyBlockEntity extends BlockEntity {
    private static final int MAX_PROGRESS = 500;
    private int progress = 0;

    private final PropertyDelegate propertyDelegate = new PropertyDelegate() {
        @Override
        public int size() {
            // This is how many properties you have. We have two of them, so we'll return 2.
            return 2;
        }

        @Override
        public int get(int index) {
            // Each property has a unique index that you can choose.
            // Our properties will be 0 for the progress and 1 for the maximum.

            if (index == 0) {
                return progress;
            } else if (index == 1) {
                return MAX_PROGRESS;
            }

            // Unknown property IDs will fall back to -1
            return -1;
        }

        @Override
        public void set(int index, int value) {
            // This is used on the other side of the sync if you're using extended screen handlers.
            // Generally you'll want to have a working implementation for mutable properties, such as our progress.

            if (index == 0) {
                progress = value;
            }
        }
    }
}

We'll implement PropertyDelegateHolder on the BE class now, so that LibGui knows about our property delegate.

public class MyBlockEntity extends BlockEntity implements PropertyDelegateHolder {
    // ...

    @Override
    public PropertyDelegate getPropertyDelegate() {
        return propertyDelegate;
    }
}

Hooking it up to the GUI

Finally, we'll have to hook this up to the GUI description. In your SyncedGuiDescription constructor, you should have a super call that's something like this:

super(MyMod.SCREEN_HANDLER_TYPE, syncId, playerInventory, getBlockInventory(context, INVENTORY_SIZE), getBlockPropertyDelegate(context));

The last parameter is the property delegate of the block. However, the default call assumes that you have no properties and will return an empty property delegate on the client. To prevent this, you need to pass your number of properties to the method call:

public class MyGuiDescription extends SyncedGuiDescription {
    private static final int PROPERTY_COUNT = 2; // This should match PropertyDelegate.size().

    public MyGuiDescription(int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) {
        super(MyMod.SCREEN_HANDLER_TYPE, syncId, playerInventory, getBlockInventory(context, INVENTORY_SIZE), getBlockPropertyDelegate(context, PROPERTY_COUNT));

        // ....
    }

Your GUI should now be ready to synchronize properties!