数据包扩展指南
概述
本页面修缮中……
注意:目前为止,仅Forge版支持数据驱动!
SmartKeyPrompts 支持通过数据包扩展按键提示功能,允许不精通 Kubejs 的整合包作者与玩家根据实际需求灵活自定义按键显示
数据包使用 MVEL 表达式语言 进行逻辑判断和动作执行,提供强大的表达式支持。
此文档的内置函数部分只适用于1.0.4.2及以上版本,低版本请看 模组内置数据包 / 模组源码作为示例
MVEL 表达式语言简介
MVEL (MVFLEX Expression Language) 是一个强大的表达式语言,支持丰富的语法特性:
基本语法特性
- 三元表达式:
condition ? value1 : value2
- 逻辑运算:
&&
(与)、||
(或)、!
(非) - 比较运算:
==
、!=
、>
、<
、>=
、<=
- 字符串操作:
+
(连接)、.startsWith()
、.contains()
等 - 空值检查:
value != null
、value == 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'
更多详细语法请参考:
数据包结构
文件路径
数据包文件应存放于:
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()
:获取主手物品IDvehicleType()
:获取当前载具类型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')"
]
}
]
}
最佳实践
命名规范
modid
:使用<原模组名>_skp
格式(表明是本模组主动提供的按键支持)- 提示文本使用翻译键(
key.modid.desc
)
性能优化
- 优先使用精确匹配代替表达式匹配
- 将复杂逻辑提取为
vars
- 条件顺序以常见优先
可维护性
- 按模组拆分文件
- 合理分组
entries
- 保持表达式简洁、变量命名清晰
注意事项
- 始终检查模组是否加载
- 处理空值和异常情况
- 充分考虑不同游戏状态
- MVEL表达式部分不要用中文!!!!!!!!!!!!!!!!!!(实在需要请加上双引号,如
"custom(modid, keyUse, \"中文\")"
jvm启动参数:-Dfile.encoding=UTF-8
)
需要更多帮助时,也欢迎查阅相关模组源码或联系作者社区。