Skip to main content

数据包扩展指南

概述

本页面修缮中……

注意:目前为止,仅Forge版支持数据驱动!

SmartKeyPrompts 支持通过数据包扩展按键提示功能,允许不精通 Kubejs 的整合包作者与玩家根据实际需求灵活自定义按键显示

数据包使用 MVEL 表达式语言 进行逻辑判断和动作执行,提供强大的表达式支持。

此文档的内置函数部分只适用于1.0.4.2及以上版本,低版本请看 模组内置数据包 / 模组源码作为示例


MVEL 表达式语言简介

MVEL (MVFLEX Expression Language) 是一个强大的表达式语言,支持丰富的语法特性:

基本语法特性

  • 三元表达式condition ? value1 : value2
  • 逻辑运算&&(与)、||(或)、!(非)
  • 比较运算==!=><>=<=
  • 字符串操作+(连接)、.startsWith().contains()
  • 空值检查value != nullvalue == null
  • 函数调用:支持调用注册的静态方法

示例表达式

// 三元表达式
keyUse == 'key.keyboard.unknown' ? 'key.mouse.right' : keyUse

// 逻辑组合
isModLoaded('tacz') && mainHandItem() == 'tacz:modern_kinetic_gun'

// 字符串匹配
vehicleType() != null && vehicleType().startsWith('immersive_aircraft:')

// 复杂条件
mainHandItem() != 'minecraft:sugar' && mainHandItem() != 'diligentstalker:stalker_master'

更多详细语法请参考:

MVEL 官方文档

MVEL2 中文语法指南


数据包结构

文件路径

数据包文件应存放于:

data/[namespace]/smartkeyprompts/key_prompts/[文件名].json

例如: data/smartkeyprompts/smartkeyprompts/key_prompts/tacz.json

文件格式

{
"modid": "按键组标识符",
"vars": {
"变量名": "MVEL 表达式"
},
"entries": [
{
"when": {
"条件变量": "期望值或表达式"
},
"then": [
"动作表达式"
]
}
]
}

字段说明

modid

  • 类型:string
  • 说明:用于标识此数据包所属模组,一般来说,填入要适配的模组id即可。

vars

  • 类型:object
  • 说明:定义可复用变量,通过 MVEL 表达式实时计算,用于简化条件判断。

entries

  • 类型:array
  • 说明:定义了一组 “触发条件 - 执行动作” 的逻辑对。每一条目按数组顺序依次进行判断与执行,匹配后则执行相应的动作。

when

  • 类型:object

  • 说明:触发条件,所有键值对需同时满足。

  • 支持:

    • 精确匹配
    • 通配符匹配(如 "immersive_aircraft:*"
    • 表达式匹配(如 "modLoaded": "true"

then

  • 类型:string[]
  • 说明:当 when 条件满足时执行的动作表达式。

内置函数参考(可提 Issues 作者酌情添加)

基础变量函数

  • player():获取当前玩家对象
  • mainHandItem():获取主手物品ID
  • vehicleType():获取当前载具类型
  • targetedEntity():获取目标实体类型

玩家状态检查

  • isInVehicle():检查玩家是否在载具中
  • isSwimming():检查玩家是否在游泳
  • isFlying():检查玩家是否在飞行
  • isCreativeMode():检查玩家是否在创造模式
  • hasItem(itemId):检查玩家是否拥有指定物品

按键相关

  • getKeyByDesc(desc):根据描述获取按键名称
  • isKeyPressedOfDesc(key):检查指定按键是否被按下

实体和环境检查

  • isTargetedEntityType(entityType):检查目标实体是否为指定类型
  • hasTargetEntity():检查是否存在目标实体
  • isCameraPlayer():检查摄像机实体是否为玩家
  • isScreenOpen():检查游戏界面是否打开

物品NBT相关

  • hasMainHandNBT(nbtPath):检查主手物品是否包含指定NBT路径
  • checkMainHandNBT(nbtPath, expectedValue):检查主手物品NBT路径的值是否匹配
  • getMainHandNBTValue(nbtPath):获取主手物品NBT路径的值
  • matchMainHandSNBT(snbt):检查主手物品NBT是否匹配SNBT格式
  • getMainHandSNBT():获取主手物品的完整SNBT

目标实体NBT相关

  • hasTargetEntityNBT(nbtPath):检查目标实体是否包含指定NBT路径
  • checkTargetEntityNBT(nbtPath, expectedValue):检查目标实体NBT路径的值是否匹配
  • getTargetEntityNBTValue(nbtPath):获取目标实体NBT路径的值
  • getTargetEntitySNBT():获取目标实体的完整SNBT

目标方块实体NBT相关

  • hasTargetBlockEntityNBT(nbtPath):检查目标方块实体是否包含指定NBT路径
  • checkTargetBlockEntityNBT(nbtPath, expectedValue):检查目标方块实体NBT路径的值是否匹配

模组和系统

  • isModLoaded(modid):检查指定mod是否已加载
  • getCurrentTime():获取当前时间戳

显示动作

  • show(modid, desc):显示按键提示
  • custom(modid, key, desc):显示自定义按键提示
  • alias(modid, key, desc):显示按键别名提示

当然,如果你会编写模组,可自行注册,请查阅注册事件


动作类型说明

表达式说明
show(modid, 'translation.key')显示标准按键提示
custom(modid, key, 'desc')显示指定按键的自定义提示
custom(modid, key1 + '+' + key2, 'desc')组合键提示

使用示例

示例 1:简单模组支持

{
"modid": "tacz_skp",
"vars": {
"modLoaded": "isModLoaded('tacz')",
"hasTaczGun": "mainHandItem() == 'tacz:modern_kinetic_gun'",
"isNotInVehicle": "!isInVehicle()"
},
"entries": [
{
"when": {
"modLoaded": "true",
"hasTaczGun": "true",
"isNotInVehicle": "true"
},
"then": [
"show('tacz_skp', 'key.tacz.shoot.desc')",
"show('tacz_skp', 'key.tacz.zoom.desc')",
"show('tacz_skp', 'key.tacz.reload.desc')"
]
}
]
}

示例 2:通配符匹配

{
"modid": "immersive_aircraft_skp",
"vars": {
"modLoaded": "isModLoaded('immersive_aircraft')",
"vehicleType": "vehicleType",
"keyInventory": "getKeyInventory()"
},
"entries": [
{
"when": {
"modLoaded": "true",
"vehicleType": "immersive_aircraft:*"
},
"then": [
"custom(modid, keyInventory, 'immersive_aircraft.slot.upgrade')",
"show(modid, 'key.immersive_aircraft.dismount')"
]
}
]
}

示例 3:组合按键与复杂条件(附带 NBT 示例)

{
"modid": "diligentstalker",
"vars": {
"modLoaded": "isModLoaded('diligentstalker')",
"keyUse": "getKeyByDesc('key.use')",
"keyShift": "getKeyByDesc('key.sneak')",
"mainHandItem": "mainHandItem()",
"targetedEntity": "targetedEntity()",
"isCameraPlayer": "isCameraPlayer()",
"isTargetedDrone": "isTargetedEntityType('diligentstalker:drone_stalker')",
"screenOpen": "isScreenOpen()",
"notHoldingSugarOrMaster": "mainHandItem() != 'minecraft:sugar' && mainHandItem() != 'diligentstalker:stalker_master'",
"hasTargetEntity": "hasTargetEntity()",
"stalkerMasterHasBind": "hasMainHandNBT('StalkerId')"
},
"entries": [
{
"when": {
"modLoaded": "true",
"mainHandItem": "diligentstalker:stalker_master",
"stalkerMasterHasBind": "true",
"screenOpen": "false",
"isCameraPlayer": "true"
},
"then": [
"custom('diligentstalker', keyUse, 'key.diligentstalker.remote_connect')"
]
},
{
"when": {
"modLoaded": "true",
"isTargetedDrone": "true",
"mainHandItem": "minecraft:sugar",
"screenOpen": "false"
},
"then": [
"custom('diligentstalker', keyShift + '+' + keyUse, 'key.diligentstalker.add_fuel')"
]
},
{
"when": {
"modLoaded": "true",
"isTargetedDrone": "true",
"screenOpen": "false",
"notHoldingSugarOrMaster": "true"
},
"then": [
"custom('diligentstalker', keyShift + '+' + keyUse, 'key.diligentstalker.container')"
]
}
]
}

示例 4:NBT完整示范

{
"modid": "minecraft_skp_nbt",
"vars": {
"isDiamondSword": "mainHandItem() == 'minecraft:diamond_sword'",
"hasSharpness": "hasMainHandNBT('Enchantments[{id:\"minecraft:sharpness\"}]')",
"sharpnessLevel5": "checkMainHandNBT('Enchantments[{id:\"minecraft:sharpness\"}].lvl', '5s')",
"displayName": "getMainHandNBTValue('display.Name')",
"isNamedExcalibur": "displayName != null && displayName.contains('Excalibur')",

"hasCustomModelData99": "checkMainHandNBT('CustomModelData', 99)",
"hasExcaliburName": "hasMainHandNBT('display.Name') && getMainHandNBTValue('display.Name').contains('Excalibur')",

"modLoaded": "isModLoaded('minecraft')"
},
"entries": [
{
"when": {
"modLoaded": "true",
"isDiamondSword": "true",
"hasSharpness": "true",
"sharpnessLevel5": "true",
"isNamedExcalibur": "true"
},
"then": [
"show('minecraft_skp_nbt', 'key.sneak')"
]
},
{
"when": {
"modLoaded": "true",
"isDiamondSword": "true",
"hasCustomModelData99": "true",
"hasExcaliburName": "true"
},
"then": [
"show('minecraft_skp_nbt', 'key.use')"
]
}
]
}

最佳实践

  1. 命名规范

    • modid:使用 <原模组名>_skp 格式(表明是本模组主动提供的按键支持)
    • 提示文本使用翻译键(key.modid.desc
  2. 性能优化

    • 优先使用精确匹配代替表达式匹配
    • 将复杂逻辑提取为 vars
    • 条件顺序以常见优先
  3. 可维护性

    • 按模组拆分文件
    • 合理分组 entries
    • 保持表达式简洁、变量命名清晰
  4. 注意事项

    • 始终检查模组是否加载
    • 处理空值和异常情况
    • 充分考虑不同游戏状态
    • MVEL表达式部分不要用中文!!!!!!!!!!!!!!!!!!(实在需要请加上双引号,如 "custom(modid, keyUse, \"中文\")" jvm启动参数:-Dfile.encoding=UTF-8

需要更多帮助时,也欢迎查阅相关模组源码或联系作者社区。