跳转至

模型变体选择(Multiplexer)参考

接口、配置和调用参考。原理说明见 multiplexer.md。

Multiplexer 是无状态变体选择器:一组 Variant 节点 + 带守卫的转移边。根据上下文(Context)选当前变体(如方块外观/模型)。定义本身不持有运行时状态 —— 一种方块类型共用一份 definition,每个实例一个 MuxState。

Multiplexer 是代码定义(Java DSL),不是 JSON。 FSM 才是数据驱动 JSON(见 fsm.md)。

何时用 Multiplexer,何时用 FSM

Multiplexer FSM
驱动方式 上下文快照选变体(ctx.property(...)) 分层状态机 + tick 推进 + 动作
状态 无(definition);每实例一个 MuxState 每实例一个完整 StateMachine
适合 开关、挡位、红石态、模型变体切换 动画时序、attack chain、locomotion
定义位置 Java 代码 data/<ns>/state_machines/*.json

简单"有电/没电换模型"用 Multiplexer;需要状态时长、动作、多层混合用 FSM。

核心 API(lib.kasuga.rendering.models.uml.dynamic.multiplexer)

// 1. 定义(共享,每类型一份)
Multiplexer<MyContext, MyVariant> def = Multiplexer.define(MyVariant::new, mux -> {
    MyVariant off = mux.variant("off", v -> { /* 变体配置:模型/材质... */ });
    MyVariant on  = mux.variant("on",  v -> { });
    mux.transition(off, on, t -> t
            .when(ctx -> ctx.property("powered").equals("true"))
            .crossFade(0.2f));
    mux.transition(on, off, t -> t.when(ctx -> ctx.property("powered").equals("false")));
    mux.initial(off);
});

// 2. 每实例一个状态
MuxState<MyVariant> state = def.newState();

// 3. 每 tick 推进(推进 cross-fade + 评估守卫,守卫命中则切换)
def.advance(state, context, dt);

// 当前选中的变体(转移期间是目标变体)
MyVariant current = state.current();

Builder 方法

方法 说明
variant(id, config) 定义一个变体,返回类型化句柄
transition(from, to, config) 加一条转移边;TransitionBuilder:
↳ .when(Predicate<C>) 守卫;为空 = 恒真
↳ .crossFade(seconds) 淡入淡出秒数;0 = 立即切换
↳ .onSwitch(Consumer<MuxState>) 切换时回调
initial(variant) 初始变体

运行时

方法 说明
newState() 建一个 per-instance MuxState(起始 = initial)
advance(state, ctx, dt) 推进 cross-fade + 评估守卫,命中则切;每 tick 调
select(ctx, state) 只读:现在会选哪个变体(不改变状态)
state.current() 当前变体
state.inTransition() / state.to() 转移中 / 目标变体(cross-fade 期间)

Minecraft 侧

MC 实现用 McContext(把方块态/红石等包成上下文快照)+ McVariant(模型/材质变体)+ McMultiplexer,核心 Multiplexer 不依赖 Minecraft。一个方块类型在注册时建一份 McMultiplexer,每个 BE newState(),#onDataChanged 或 tick 里 advance(state, ctx, dt) 并把 state.current() 喂给渲染选变体。

与 FSM 组合

Multiplexer 选"用哪个模型变体",FSM 驱动"那个模型的动画时序"。两者可叠加:Mux 选变体 → 该变体对应的 ModelInstance 再挂一个 FSM PoseDriver 跑动画。