SmartRender 兼容(SmartRender Compat)

基本信息

属性 值
类型 客户端反射兼容性垫片
实现类 roadhog360.simpleskinbackport.core.compat.SmartRenderCompat
反射目标 net.smart.render.ModelRotationRenderer.UpdateLocals()
适用端 客户端
启用条件 Loader.isModLoaded("SmartRender") + tryInitSmartRenderFields 成功

功能

SmartRender (makamys 分支的 Smart Moving 渲染器扩展) 会复制 ModelRenderer 字段的本地缓存。当本 mod 的 MixinModelBiped 重建 displayList 时,必须通知 SmartRender 同步更新它的内部缓存,否则 GL 状态错乱。

初始化流程

ClientProxy.preInit 调用 SmartRenderCompat.tryInitSmartRenderFields():

public static boolean tryInitSmartRenderFields() {
    if (Loader.isModLoaded("SmartRender")) {
        try {
            modelRotationRendererSmartRendererClass = Class.forName("net.smart.render.ModelRotationRenderer");
            updateLocalsFunc = modelRotationRendererSmartRendererClass.getDeclaredMethod("UpdateLocals");
            updateLocalsFunc.setAccessible(true);
            return true;
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            SimpleSkinBackport.LOG.warn("Smart Render compatibility handler failed. Prepare for rendering errors.");
            e.printStackTrace();
            return false;
        }
    }
    return false;
}

含义:仅在 SmartRender 已安装时通过反射拿到 UpdateLocals Method 句柄。失败时(异常或未安装)updateLocalsFunc == null,smartMovingCompatEnabled() 返回 false,整个同步块失效。

调用流程

Utils.createDisplaylistFor(ModelRenderer renderer) 中:

public static int createDisplaylistFor(ModelRenderer renderer) {
    renderer.displayList = 0;  // OptiFine for some reason checks if the display list is 0 and things get fucky
                               //   if it isn't
    renderer.compileDisplayList(0.0625F);
    SmartRenderCompat.updateSmartRenderFields(renderer);  // 通知 SmartRender
    return renderer.displayList;
}

updateSmartRenderFields 实现:

public static void updateSmartRenderFields(ModelRenderer... renderers) {
    if (smartMovingCompatEnabled()) {
        for (ModelRenderer renderer : renderers) {
            invokeUpdate(renderer);
        }
    }
}

private static void invokeUpdate(ModelRenderer renderer) {
    if (modelRotationRendererSmartRendererClass.isAssignableFrom(renderer.getClass())) {
        try {
            updateLocalsFunc.invoke(renderer);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
}

只在 renderer 实际是 ModelRotationRenderer 子类时才调用 —— 即仅当 SmartRender 包装了它。

调用入口

SmartRenderCompat.updateSmartRenderFields 在以下场景被调用:

入口 位置
Utils.createDisplaylistFor ArmPair.of(...) 中
MixinModelBiped.ssb$setSlim SmartRenderCompat.updateSmartRenderFields(bipedLeftArm, bipedRightArm)

数值

数值 值 来源
反射类全限定名 net.smart.render.ModelRotationRenderer Class.forName(...)
反射方法 UpdateLocals(无参) getDeclaredMethod("UpdateLocals")
displayList 重置值 0 renderer.displayList = 0
compileDisplayList scale 0.0625F(Minecraft 默认) compileDisplayList(0.0625F)
同步是否启用 updateLocalsFunc != null smartMovingCompatEnabled()

关联机制

步骤 位置
1. preInit 反射初始化 ClientProxy.preInit → SmartRenderCompat.tryInitSmartRenderFields
2. Mixin 重建 arm 时调用 MixinModelBiped.ssb$setSlim
3. ArMixine.of(…) 创建 Utils.createDisplaylistFor(left) + Utils.createDisplaylistFor(right)
4. SmartRender 内部缓存同步 updateLocalsFunc.invoke(renderer)

第三方 mod 集成

  • SmartRender (makamys)(可选):反射调用 ModelRotationRenderer.UpdateLocals。源码注释明确建议用 makamys 维护的构建,原版 Smart Moving 未做适配。

相关条目