Java环境下能否转换枚举类型或为CustomNPC已有枚举新增材料条目?
可行的无新增类实现方案有两种,均基于Java反射实现,不需要修改CustomNPC本身的代码:
方案1:动态向EnumNpcToolMaterial枚举新增条目
Java枚举本质是持有静态实例的特殊类,所有枚举实例都存储在类内部的$VALUES数组中,可通过反射修改该数组实现新增条目,适合需要让CustomNPC其他逻辑也识别新增材质的场景。
你可以在Mod加载的preInit阶段执行如下代码:
// 1. 获取枚举的构造器 Constructor<EnumNpcToolMaterial> constructor = EnumNpcToolMaterial.class.getDeclaredConstructor( String.class, int.class, // 枚举默认隐含的两个参数:枚举名称、ordinal序号 int.class, int.class, float.class, int.class, int.class // 枚举自定义的五个参数 ); constructor.setAccessible(true); // 2. 构造新的枚举实例,这里以自定义黑曜石材为例 EnumNpcToolMaterial obsidianMaterial = constructor.newInstance( "OBSIDIAN", EnumNpcToolMaterial.values().length, // 名称用大写,序号接在原有枚举最后 3, 2000, 7.0F, 5, 2 // 对应harvestLevel、maxUses、efficiency、damage、enchantability的自定义值 ); // 3. 修改枚举的$VALUES数组,把新实例加进去 Field valuesField = EnumNpcToolMaterial.class.getDeclaredField("$VALUES"); valuesField.setAccessible(true); EnumNpcToolMaterial[] oldValues = (EnumNpcToolMaterial[]) valuesField.get(null); EnumNpcToolMaterial[] newValues = Arrays.copyOf(oldValues, oldValues.length + 1); newValues[newValues.length - 1] = obsidianMaterial; valuesField.set(null, newValues);
后续你可以直接用构造出来的obsidianMaterial实例作为参数调用new ItemShield(),也可以正常通过EnumNpcToolMaterial.valueOf("OBSIDIAN")获取该实例。
方案2:直接构造枚举实例传入(无需修改原有枚举列表)
如果你只需要给ItemShield构造方法传参,不需要其他逻辑识别这个新增材质,可以省略修改$VALUES数组的步骤,直接反射构造EnumNpcToolMaterial实例传入即可,逻辑更轻量,不会影响原有枚举的遍历逻辑。
Constructor<EnumNpcToolMaterial> constructor = EnumNpcToolMaterial.class.getDeclaredConstructor( String.class, int.class, int.class, int.class, float.class, int.class, int.class ); constructor.setAccessible(true); EnumNpcToolMaterial customMaterial = constructor.newInstance( "CUSTOM", 999, // 序号随便填,只要你不需要遍历枚举就不会有问题 3, 1500, 8.0F, 4, 15 ); // 直接传customMaterial给ItemShield构造方法即可 ItemShield customShield = new ItemShield(你的物品ID, customMaterial);
注意事项
两种方案均属于Java非标准操作,仅适合整合包自用场景,如果要公开发布Mod建议还是保留你现在自定义盾牌类的实现,避免和其他修改同枚举的Mod产生冲突。
内容的提问来源于stack exchange,提问作者AHuIci
相关产品推荐
相关产品推荐

