创建
基础
TrMenu 的菜单是以 YAML (.yml) 文件格式配置、读取加载的因此,创建一个新的菜单,你可以通过新建一个 YAML 文件开始
路径
菜单文件可以放在默认菜单目录 (menus)中或自定义路径(需要自行配置)菜单文件名(不包括拓展名后缀)即是菜单的唯一 ID,重复 ID 的菜单仍然会被加载,但会影响开启命令的正常工作
配置
菜单的配置项将在接下来的章节详细解析请先浏览下方所提供的示例模式,快速了解菜单基本结构
# 容器显示的标题
Title: 'TrMenu'
# 容器标题刷新的时间
Title-Update: 40
# 菜单布局
Layout: []
# 菜单布局 - 玩家容器
PlayerInventory: []
# 菜单选项
Options:
# 是否启用参数
Arguments: false
# 默认参数填充
Default-Arguments: [ ]
# 非上锁槽位
Free-Slots:
- 71
- 72
# 默认页码
Default-Layout: 0
# 是否隐藏玩家容器物品
Hide-Player-Inventory: false
# 最小点击延时
Min-Click-Delay: 200
# 强制依赖的 PlaceholderAPI 拓展
Depend-Expansions: [ 'server', 'player', 'progress', 'animations' ]
# 菜单绑定
Bindings:
# 命令
Commands:
- '(?i)example(-)?(gui)?(s)?'
# 物品特征
Items:
- 'material:compass'
- 'material:clock,lore:OPEN_MENU'
- 'texture:eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDRmNDUyZDk5OGVhYmFjNDY0MmM2YjBmZTVhOGY0ZTJlNjczZWRjYWUyYTZkZmQ5ZTZhMmU4NmU3ODZlZGFjMCJ9fX0='
# 菜单事件反应
Events:
# 开启事件
Open:
- condition: 'perm *trmenu.use'
actions:
- 'sound: BLOCK_CHEST_OPEN-1-0'
deny:
- 'sound: ENTITY_ITEM_BREAK-1-0'
- 'title: `&c&lPermission Required` `&7&lYou need permission &6<rmenu.use &7<o open this menu` 15 20 15'
- 'return'
# 关闭事件
Close:
- 'sound: BLOCK_CHEST_CLOSE-1-0'
# 菜单的图标主体
Icons:
# 图标 Id
'Close':
# 显示属性更新频率
update: []
# 子图标重新计算频率
refresh: -1
# 显示部分
display: []
# 动作部分
actions: []
# 定时任务
Tasks:
# 任务 ID
tikTok:
# 任务周期 (in ticks)
period: 80
# 任务反应 (reactions)
task:
- condition: '$ sender.isOp()'
actions:
- 'sound: BLOCK_NOTE_BLOCK_BIT-1-2'
# 内置自定义 JavaScript 函数
Functions:
id: 'content'
结构
- 标题
- 单个或多个标题
- 标题更新周期
- 布局
- 菜单布局
- 玩家容器布局
- 选项
- 默认补全参数
- 默认布局页码
- 是否隐藏玩家容器物品
- 自由槽位
- 防频繁点击间隔
- 需要依赖的 PlaceholderAPI 拓展
- 绑定
- 绑定正则命令
- 绑定物品特征
- 事件
- 开启菜单执行动作
- 关闭菜单执行动作
- 图标
- 内置脚本
- 周期任务
配置
标题
示例
#
# 菜单的标题, 支持动态标题周期切换
# 标题支持配置颜色 & 函数变量
#
Title:
- 'Hello, TrMenu!'
- 'Hello, %player_name%!'
- 'Support Animated Titles'
#
# 若有多个标题, 动态切换的周期 (ticks)
#
Title-Update: 40
#
# 静态标题
#
Title: 'TrMenu Menu'
#
# 此项可以不用写,默认值即是 -1
#
# Title-Update: -1
注意
- 容器标题本身是不支持修改的,动态标题实现的原理是通过发送
PacketWindowOpen
包再打开一个新的容器,并重新发送容器内所有物品的数据包 - 动态标题的周期性更新是全局菜单适用,不支持分页独立配置
- 若需不同页面不同标题,有两种实现方式
- 动态标题配置函数变量,对页码进行判断
- 配置静态标题,切页后调用动作二次修改标题
布局
示例
#
# 菜单的布局功能
# 你可以用 ` ` 来标记设置多个字符名称图标的位置
#
Layout:
- '########`Close`'
- ' '
- ' '
- ' '
- '########`Next`'
#
# 玩家容器菜单的布局
#
PlayerInventory:
- ' '
- ' '
- ' '
- ' '
每个字符代表一个图标在菜单中的位置,你也可以用 ` 将字符串包裹起来,从而不受限于单个字符字符即是图标的唯一 ID,通过布局实现可视化编辑从而不再需要为图标单独设置槽位布局的行数将同时定义箱子容器的大小玩家容器菜单布局仅限 4*9 大小
多页
Layout:
- - '########`Close`'
- ' '
- ' '
- ' '
- '########`Next`'
- - '########`Close`'
- ' '
- ' * '
- ' '
- '`Pre`########'
布局功能可以支持多个布局,从而在同一个菜单中快速实现多页功能
PlayerInventory 同理对应
注意
- 若无 玩家容器菜单布局 与 菜单布局 对应,则在该菜单页玩家容器为空
- 标识图标的字符支持汉字
选项
示例
#
# 菜单的选项设置
#
Options:
# 是否启用菜单传参功能 (默认开启)
Arguments: true
# 默认填充参数
Default-Arguments: []
# 默认布局页码
Default-Layout: 0
# 自由槽位
Free-Slots:
- '71-73'
# 是否隐藏玩家容器
Hide-Player-Inventory: true
# 防频繁点击的间隔
Min-Click-Delay: 200
# 强制需要依赖的 PlaceholderAPI 拓展变量
Depend-Expansions: ['server', 'player', 'progress']
注意
- 若设置 默认填充参数 ,则将自动补全玩家未提供的参数,例如
- Default-Arguments: [“TabooLib”, “Virus”]
- 玩家提供的参数为 [“TabooLib”], 则第二个参数将自动补全为 Virus
- 默认菜单布局页码 即在未指定页码的情况下默认打开菜单后初次显示的页码
- 依赖PAPI拓展 菜单开启时将检测是否安装完整,否则拒绝开启并自动请求下载
绑定
示例
#
# 菜单绑定的快捷打开方式
#
Bindings:
# 绑定命令, 支持正则
Commands:
- 'tester'
# 绑定到物品特征
Items:
- 'material:compass'
注意
- 绑定命令支持正则匹配,例如 添加 (?i) 前缀可以忽略大小写
- 绑定命令支持空格 & 其它参数,插件将自动匹配并读取玩家提供的真实参数
- 了解绑定 物品特征 的详细写法,请查看下面章节
事件
示例
#
# 菜单的事件处理
#
Events:
# 开启菜单
Open:
- condition: 'perm *trmenu.use'
actions:
- 'sound: BLOCK_CHEST_OPEN-1-0'
deny:
- 'sound: ENTITY_ITEM_BREAK-1-0'
- 'title: `&c&lPermission Required` `&7&lYou need permission &6<rmenu.use &7<o open this menu` 15 20 15'
- 'return'
# 关闭菜单
Close:
- 'sound: BLOCK_CHEST_CLOSE-1-0'
注意
- 事件配置的对象均是反应(动作组)
- 若执行 RETURN 动作,则事件将取消
内置函数
示例
Functions:
flash: |-
function flash() {
var display = new Date().getSeconds() % 2 == 0
return display ? args[0] : " "
}
flash()
- 在该例中,我们在 Functions 下定义了一个
flash
函数,本函数根据判断当前系统的时间(秒)是否为偶数,决定是返回传入参数还是一个空格 - 该函数可以实现闪烁的动画效果,且支持自定义参数参数作为闪烁符号
注意
- 调用格式为
${[funcName]_[Arg1]_[Arg2]}
例如 ${flash_>} - 默认函数上方将自动添加行
var args = new Array()
并写入参数,因此在内置函数中传入的参数可以直接通过 args 数组的形式使用
拓展例子
bStats:
servers: 'vars("${bStats.query_servers_&a_&7 servers}")'
players: 'vars("${bStats.query_players_&6_&7 players}")'
menus: 'vars("${bStats.query_menus_&2_&7 menus}")'
opens: |-
function opens() {
var data = utils.query("https://bstats.org/api/v1/plugins/5742/charts/menu_open_counts/data?maxElements=1")
if (data.has()){
return "&b" + data.asJson().getAsJsonArray().get(0).getAsJsonArray().get(1) + "&7"
}
return "&8Loading." + vars("${flash_.}") + "&7"
}
opens()
query: |-
function query() {
var data = utils.query("https://bstats.org/api/v1/plugins/5742/charts/" + args[0] + "/data?maxElements=1")
if (data.has()){
return args[1] + data.asJson().getAsJsonArray().get(0).getAsJsonArray().get(1) + args[2]
}
return "&8Loading." + vars("${flash_.}")
}
query()
周期任务
示例
#
# 菜单自定义周期性任务
#
Tasks:
# 任务 Id
tikTok:
# 周期 ( Ticks )
period: 20
# 反应
task:
- condition: '$ sender.isOp()'
actions:
- 'sound: BLOCK_NOTE_BLOCK_BIT-1-2'
注意
- 每个周期任务由 任务 ID、周期、反应 三部分组成
- 切换页码不会终止周期任务
图标
结构
图标 ID
- 更新 周期
- 重新筛选计算子图标 周期
- 是否继承 *
- 条件 *
- 优先级 *
- 槽位
- 显示部分
- 材质
- 属性
- NBT
- 标签
- 发光
- 数量
- 名称
- 描述
- 交互处理
- <类型>:反应
* 表示该属性为子图标设计更新/刷新 周期 和 槽位是图标全局属性,不支持子图标另行设置
设置
更新周期
- 更新周期包括 4 个(材质,名称,Lore,槽位)
- 你可以通过配置数组的形式独立设置它们
# 设置一个值,同时应用到 材质,名称,Lore,槽位 中
update: 20
# 不完全设置
# 分别设置材质,名称,Lore的更新周期为 20, -1, 15
# 槽位的更新周期将选取其中最高的一个,即 20
update: [20, -1, 15]
# 完全配置, 即按顺序分别对应
update: [-1, 5, 25, 30]
- 不配置更新周期项,图标将默认不更新
- 更新周期应与默认图标同级节点,子图标不支持自定义更新周期
- 插件会根据属性是否需要更新(包含动画、变量)自动分配周期,因此不必在这麻烦配置
刷新周期
- 按优先级、条件重新计算子图标
- 只有存在子图标时,此项才有效
- 使用动作 Refresh,可以主动刷新图标,达到同样效果
refresh: 20
图标槽位
- 针对静态槽位的图标,推荐通过 布局 功能来定义图标槽位
- 手动配置槽位将覆写布局的配置
slots: 6
slots:
- 1
- 2
- 3
# 4-6 = [4, 5, 6]
- '4-6'
- '${js: varInt("%player_health%")}'
- 7
# 动态槽位,List<List<Int>> 嵌套模式
slots:
- - 0
- 1
- - 1
- 2
- - 2
- 3
* 继承
inherit: true
- 无论配置与否,默认子图标都将继承主图标的材质
- 开启子图标继承,将额外继承主图标的名称,Lore
- “继承” 是指子图标未配置的前提下,继承状态下子图标仍然可以通过配置来覆写
- 默认继承与否可通过编辑
settings.yml
文件来设置
* 条件
* 子图标的属性,条件计算结果为真时才可能显示此子图标
condition: 'perm *trmenu.use'
* 优先级
决定该子图标的权重(筛选子图标时的顺序先后)
priority: 20
- 该项仅对子图标有效
- 若不设置,则默认优先级为 0
- 选取条件子图标时,按优先级升序依次计算子图标到满足条件的为止,即优先级最小的图标最先计算
在实际配置 YAML 文件时,此项为非必须项插件会根据图标的 “配置位置” ,按顺序自动的分配一定优先级,例如
Icons:
'A':
display:
material: grass_block
icons:
- condition: 'perm *op'
display:
material: beacon
- condition: 'perm *mvp.user'
display:
material: diamond block
- condition: 'perm *vip.user'
display:
material: gold block
会先计算条件为 perm *op
的子图标,再依次 perm *mvp.user
、perm *vip.user
显示
示例
# 图标 Id
'Close':
# 显示属性更新频率
update: []
# 显示部分
display:
# 材质,支持多个,动态更新
material: ''
# 名称,支持多个,动态更新
name: ''
# Lore 描述,支持多组,动态更新
lore: []
# NBT
nbt:
key: value
# 物品标签, List 形式
flags: []
# 物品数量
amount: ''
# 发光效果
shiny: 'true'
材质
普通材质
material: 'Red Stained Glass Pane'
material: 'Wool:3'
- 材质实现动画的方式就是写成集合形式,将在设定周期内循环切换
- 普通材质也支持使用函数变量
物品仓库
- TrMenu 内置的物品存储调用功能,通过子命令 Item 实现
material: 'repo:myCustomItem'
material: 'repo:%custom_variable_whichreturnstheid%'
转化格式 JSON
- 通过
/trmenu item toJson
转化得到的物品文本格式 - 该方法能支持一切形式的物品
material: '{"type":"DIAMOND_SWORD","data":0,"amount":1,"meta":{"Damage":{"type":"INT","data":0}}}'
头颅材质
玩家头颅
material: 'head:%player_name%'
material: 'head:BlackSky'
- TrMenu 采用本地 NMS 读取在线玩家的皮肤 + 异步联网读取离线正版玩家 皮肤材质的形式,不卡线程
- 已对 SkinsRestorer 进行完整支持,能够获取到玩家显示的皮肤!
自定义纹理头颅
material: 'head:eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDRmNDUyZDk5OGVhYmFjNDY0MmM2YjBmZTVhOGY0ZTJlNjczZWRjYWUyYTZkZmQ5ZTZhMmU4NmU3ODZlZGFjMCJ9fX0='
material: 'head:44f452d998eabac4642c6b0fe5a8f4e2e673edcae2a6dfd9e6a2e86e786edac0'
物品源
- TrMenu 对挂钩插件物品支持的实现
- 统一格式为
source:<ID>:<INPUT>
HeadDatabase
material: 'source:HeadDatabase:myHead'
material: 'source:HDB:random'
Oraxen
material: 'source:ORAXEN:itemId'
ItemsAdder
material: 'source:ITEMADDER:itemId'
material: 'source:IA:anotherItemId'
* 材质参数
附加值
material: '3{data=2}'
Model Data
# 1.14+
material: 'coal{model-data=15}'
皮革染色
material: 'leather chestplate {dye=255,255,0}'
旗帜模式
material: 'white banner {banner=RED MOJANG,WHITE}'
名称
示例
'Next':
display:
material: 'Cyan Stained Glass Pane'
name: '&bN&3ext Page'
'Close':
update: [25, 5, -1, -1]
display:
materials:
- 'Red Stained Glass Pane'
- 'Orange Stained Glass Pane'
# 动态名称,更新周期 5 ticks
name: ['&cC&7lose', '&cCl&7ose', '&cClo&7se', '&cClos&7e', '&cClose']
描述
示例
# 嵌套 List,多组动态 Lore
lores:
- - '&7Thanks &f:> &7for using!'
- - '&7Thanks &f:) &7for using!'
# 静态 Lore 描述
lore:
- 'Hello There'
- 'Hello TrMenu!'
条件
此功能将在每次更新 Lore 时进行计算条件,可能影响插件性能表现
lore:
- 'Line 1'
- 'Line 2'
# 当玩家有 vip.user 权限时显示此行
- 'You are VIP User {condition=perm *vip.user}'
- 'Line 3'
属性
数量
# 静态数量
amount: 10
# 动态数量 (需要是返回数值的变量)
amount: '${js: varInt("%server_time_s%") + 1}'
发光
# 直接设置布尔值,开启或关闭(默认:关闭)
# 实质是为物品添加一个附魔效果 & 隐藏附魔显示的标签,因此不能让所有物品都发光
shiny: true
# 动态效果(条件表达式)
shiny: 'all [perm *vip.user money *100]'
标签
flags:
- 'HIDE_ENCHANTS'
- 'HIDE_ATTRIBUTES'
可用物品标签
- HIDE_ENCHANTS
- HIDE_ATTRIBUTES
- HIDE_UNBREAKABLE
- HIDE_POTION_EFFECTS
- HIDE_DESTROYS
- HIDE_PLACED_ON
NBT
nbt:
balabala: 12345
交互
示例
'Close':
update: [-1, 5, -1, -1]
display:
material: Red Stained Glass Pane
name: ['&cC&7lose', '&cCl&7ose', '&cClo&7se', '&cClos&7e', '&cClose']
# 动作部分
actions:
# 点击类型 - 反应
all: close
'*':
update: [-1, 5, 20, -1]
display: # ...
# 动作部分
actions:
# 点击类型(左键)
left:
- 'set-meta: icon_server_hide true'
- 'sound: BLOCK_NOTE_BLOCK_BIT-1-0'
- 'refresh: *'
类型
ALL
LEFT
RIGHT
SHIFT_LEFT
SHIFT_RIGHT
OFFHAND
NUMBER_KEY
NUMBER_KEY_1
NUMBER_KEY_2
NUMBER_KEY_3
NUMBER_KEY_4
NUMBER_KEY_5
NUMBER_KEY_6
NUMBER_KEY_7
NUMBER_KEY_8
NUMBER_KEY_9
MIDDLE
DROP
CONTROL_DROP
ABROAD_LEFT_EMPTY
ABROAD_RIGHT_EMPTY
ABROAD_LEFT_ITEM
ABROAD_RIGHT_ITEM
LEFT_MOUSE_DRAG_ADD
RIGHT_MOUSE_DRAG_ADD
MIDDLE_MOUSE_DRAG_ADD
DOUBLE_CLICK
反应 (动作组)
常规
actions:
- 'tell: Hello, %player_name%'
actions: 'tell: Hello, %player_name%'
三元动作组
actions:
all:
- condition: 'js: utils.chance(0.1)'
actions:
- 'tell: Prize 1'
- 'return'
- condition: 'js: utils.chance(0.5)'
actions:
- 'tell: Prize 2'
- 'return'
- condition: ''
actions:
- 'tell: Prize 3'
注意
- 动作做的执行结果取决于是否有 return 动作返回,若有返回则为 false
条件
引入
“条件表达式” 是可用在以下场景中使用的单个字符串
- 动作参数
- 反应(动作组)条件
- 子图标筛选条件
其执行结果应当返回布尔值(Boolean),即 true
/ false
目前,TrMenu 以支持 Kether 和 JavaScript 两种类型的表达式作为条件编译使用其中默认情况下统一调用 Kether *(推荐)
使用
Kether 表达式直接使用,JavaScript 表达式需加以 js:
前缀且规范变量处理例如创建一个当玩家有 vip.user
权限或余额大于等于 1000
时才成立的条件
- Kether:
any [ perm *vip.user money *1000 ]
- JavaSctipt:
js: player.hasPermission("vip.user") || utils.hasMoney(player, 1000.0)
两种语法的格式可用通过 SCRIPT
章节进一步学习
进阶
插件命令
主命令
插件的主命令
- 名称:
trmenu
menu
- 权限:
trmenu.access
List
列出已加载的菜单
- 权限:
trmenu.command.list
- 参数
- <Filter> 过滤菜单名称
Open
打开指定菜单
- 权限:
trmenu.command.open
- 参数
- [ID]:<Page> 菜单名称和指定页码
- <Player> 指定玩家,不填则默认自己
- <菜单参数> 传入的菜单参数,作为变量使用
- 示例
trmenu open Example BlackSKY
为 BlackSKY 玩家打开 Example 菜单trmenu open Shop:3
为自己打开 Shop 菜单,页码 3
Reload
重新载入菜单
- 权限:
trmenu.command.reload
Template
模板创建功能,快速布局菜单(当前仅支持箱子容器)
- 权限:
trmenu.command.template
- 参数
- <Rows> 菜单的行数大小(1~6)
Action
测试 TrMenu 动作
- 权限:
trmenu.command.action
- 参数
- [ID] 执行动作玩家对象的名称
- [Action] 动作行
- 注意
- 默认将向命令执行者打印动作返回 & 相关消耗
- 隐藏此打印功能需要在动作行最前面加以
#
标记
Item
管理控制物品
- 权限:
trmenu.command.item
- 参数
- [Method] 操作类型
- toJson 转换手中物品为 JSON 文本格式
- fromJson 将参数2的文本内容转换为物品对象
- save 保存物品到物品仓库
- get 取得物品从物品仓库
- delete 删除物品自物品仓库
- <Value> 值
- [Method] 操作类型
Sounds
预览音效
- 权限:
trmenu.command.sounds
- 参数
- <Filter> 过滤音效名称
Debug
调试功能
- 权限:
trmenu.command.debug
菜单传参
功能启用
若不进行任何配置,菜单传参功能默认是开启的,若遇到命令不兼容情况,可以通过选项关闭
传递方式
- 绑定的自定义开启命令传递
- 插件开启菜单命令传递
- 调用动作二次修改
如何使用
例如玩家当前的参数为 apple, juice, orange,即大小为 3 的一个数组在菜单几乎所有地方都可以当作变量使用,{0} 将返回 apple, {1} 返回 juice, 依此类推
注意
- 默认情况下,关闭菜单不会删除现有参数
物品特征
格式
- 同一个物品的不同特征匹配,用 , 分开
- 多个物品特征用 ; 分开
示例
material:DIAMOND,amount:64 ; material:EMERALD,amount:32
特征
- 材质: Material
- 损伤值: Data
- 数量: Amount
- 名称: Name
- 描述: Lore
- 头颅材质: Texture
- ModelData
函数变量
{}
若需要使用 }
右花括号,请转义使用 \}