ModularUI2 值与同步接口(api/value、api/value/sync)

基本信息

属性 值
包路径 com.cleanroommc.modularui.api.value / .api.value.sync
api/value 文件数 11
api/value/sync 文件数 11
同步值实现 com.cleanroommc.modularui.value.sync(36 个文件,非 api 包)

api/value 描述「控件里存什么值」,api/value/sync 描述「这个值如何在服务端与客户端之间保持一致」。 两套接口是正交的:一个 IValue 不一定同步,一个 ISyncValue 也未必绑定到 IValue。

功能

值类型接口(api/value,11 个)

全部为泛型接口,泛型参数即值类型:

接口 值类型 说明
IValue<T> 任意 顶层契约
IStringValue<T> String 可读为文本(用于文本框、按钮标题)
IBoolValue<T> boolean 开关
IByteValue / IShortValue / IIntValue / ILongValue 整型族 数值输入
IFloatValue / IDoubleValue 浮点族 数值输入
IEnumValue<T extends Enum<T>> 枚举 下拉选择
ISyncOrValue — 桥接接口:把 IValue 与 SyncHandler 统一为同一插槽(SyncHandler 也实现它,见 value/sync/SyncHandler.java:32)

IMathValue 不在 api/value 下,而在 api/ 根目录(src/main/java/com/cleanroommc/modularui/api/IMathValue.java)。

ISyncOrValue 是整个同步体系的关键设计:一个 Widget 只需实现 ISynced, 然后接收 IValue 或 SyncHandler 两者之一即可(api/widget/ISynced.java:55 isValidSyncOrValue)。

同步值接口(api/value/sync,11 个)

接口 说明
IValueSyncHandler<T> 值同步处理器顶层契约
IBoolSyncValue / IStringSyncValue 布尔 / 字符串
IByteSyncValue / IShortSyncValue / IIntSyncValue / ILongSyncValue 整型族
IFloatSyncValue / IDoubleSyncValue 浮点族
IValueSyncHandler(泛型) 泛型容器同步(配合 GenericSyncValue.Builder)
IServerMouseAction 服务端处理鼠标操作(serverMouseClick() 等)
IServerKeyboardAction 服务端处理键盘操作(serverKeyClick() 等)

后两者是双向同步的关键:客户端控件(如 ToggleButton)收到点击时, 通过 DynamicSyncHandler 把动作发给服务端,由服务端决定是否真的改变值, 再回写给所有客户端——避免客户端单方面改值造成作弊。

具体同步值实现见 同步处理器。

交互

值在控件上的挂载点

值与同步的唯一挂载点是 Widget(widget/Widget.java:47),它同时 implements IPositioned<W>, ITooltip<W>, ISynced<W>:

方法 位置 状态
getValue() 返回 IValue<?> Widget.java:713 现行
syncHandler(String name, int id) Widget.java:727 现行、推荐——按「同步键名 + id」绑定,不要求该控件在客户端和服务端两边都定义
getSyncHandler() Widget.java:700 现行;未同步时抛 IllegalStateException("Widget is not initialised or not synced!")
isSynced() Widget.java:689 现行
setValue(IValue<?>) Widget.java:738 protected + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "3.2.0")
setSyncHandler(SyncHandler<?>) Widget.java:750 protected + 同上两个废弃标注

ISynced 接口侧还有 4 个同样标注 ScheduledForRemoval(inVersion = "3.2.0") 的 @Deprecated 方法: isValidSyncHandler(api/widget/ISynced.java:42)、castIfTypeElseNull(:76)、以及同段其余两处。 编写新代码应直接用 syncHandler(String,int) + PanelSyncManager。

IValueWidget

api/widget/IValueWidget.java:8 只有一个方法 T getWidgetValue()(:13), 是纯标记接口。默认实现 widgets/ValueWidget.java:6(ValueWidget<W, T> extends Widget<W> implements IValueWidget<T>) 只是一个不可变持有者:构造器 ValueWidget(T widgetValue)(:10)+ getWidgetValue()(:15), 共 17 行,没有额外的构建器方法——它不是「带构建器的值控件」。

其他 mod 编程时的两种典型用法:

  1. 纯本地值(客户端界面):把值塞给具体控件自己的 setter(如 TextFieldWidget 的文本、ToggleButton 的选中态)
  2. 服务端权威值:在服务端 ModularSyncManager 注册同步处理器,客户端用 syncHandler(name, id) 绑定

具体同步值实现见 同步处理器。

相关条目