跳到主要内容

config.yml

Main:
# MM物品默认保存路径
MMItemsPath: MMItems.yml
# 是否开启debug模式
Debug: false
# 将消息设置为""则不进行提示
Messages:
# 一些消息的提示类型
type:
# Pack/Items
# 给予物品包是发送物品包提示还是发送所有物品提示
givePackMessage: Pack
# 玩家不在线提示
invalidPlayer: §e[NI] §6玩家不在线或不存在
# 给予成功提示
successInfo: §e[NI] §6成功给予 §f{player} §a{amount} §6个 §f{name}
# 被给予成功提示
givenInfo: §e[NI] §6你得到了 §a{amount} §6个 §f{name}
# 给予物品包成功提示
successPackInfo: §e[NI] §6成功给予 §f{player} §a{amount} §6个 §f{name} §6物品包
# 被给予成功物品包提示
givenPackInfo: §e[NI] §6你得到了 §a{amount} §6个 §f{name} §6物品包
# 给予成功提示
dropSuccessInfo: §e[NI] §6成功在 §a{world} §6的 §a{x},{y},{z} §6掉落了 §a{amount} §6个 §f{name}
# 未知物品提示
unknownItem: §e[NI] §6找不到ID为 §a{itemID} §6的物品
# 未知物品包提示
unknownItemPack: §e[NI] §6找不到ID为 §a{packID} §6的物品包
# 对应ID物品已存在提示
existedKey: §e[NI] §6已存在ID为 §a{itemID} §6的物品
# 未知解析对象提示
invalidParser: §e[NI] §6不能针对后台解析物品, 请指定一个玩家
# 错误发送者提示
onlyPlayer: §e[NI] §6该指令仅可玩家使用
# 保存成功提示
successSaveInfo: §e[NI] §6成功将 §f{name} §6以ID §a{itemID} §6保存至 §a{path}
# MM物品转换完毕提示
mmImportSuccessInfo: §e[NI] §6成功将所有MM物品保存至 §a{path}
# 物品到期删除提示
itemExpirationMessage: §e[NI] §6你背包中的 §f{itemName} §6已到期删除
# 物品列表内, 点击获取物品提示
clickGiveMessage: §e点击获取该物品
# 不要保存空气提示
airItem: §e[NI] §6请不要试图保存空气, 谢谢合作
# 输入无效数字提示
invalidAmount: §e[NI] §6无效数字
# 输入无效世界提示
invalidWorld: §e[NI] §6无效世界
# 输入无效坐标提示
invalidLocation: §e[NI] §6无效坐标
# 权限不足提示
insufficientPermissions: §e[NI] §6权限不足
# 物品冷却提示
itemCooldown: §e物品冷却中! 请等待{time}
# 重载完毕提示
reloadedMessage: §e[NI] §6重载完毕
# 无效NBT提示
invalidNBT: §6[NI] §cNBT加载失败, 请勿在列表型NBT中混用键值对, 数字及字符串
# MM生物穿戴物品失败提示
equipFailed: §e[NI] §6在尝试给ID为 §f{mobID}§6 的MM怪物穿戴ID为 §f{itemID}§6 的NI物品时发生了错误.
# 错误物品提示
invalidItem: '§6[NI] §c物品加载失败, 物品可能缺损数据, 物品ID: §6{itemID}'
# 给予失败提示
failureInfo: '§e[NI] §6物品给予失败, 可能原因: 物品未配置材质/玩家已下线'
# 缺少前置插件提示
invalidPlugin: '§e[NI] §6未发现前置插件: {plugin}'
# 位置物品材质提示
invalidMaterial: '§e[NI] §6物品 {itemID} 使用了未知的材质 {material}'
# 掉落物归属提示信息
invalidOwnerMessage: §6无法拾取该物品, 该物品的拥有者是 §f{name}
# 物品包掉落提示信息
dropPackSuccessInfo: §e[NI] §6成功在 §a{world} §6的 §a{x},{y},{z} §6掉落了 §a{amount} §6组 §f{name} 物品包
# 指令帮助信息
Help:
prefix: |-
§6====================§eNeigeItems§6====================
§6==================[]为必填, ()为选填==================
suffix: §6================<< §e{prev} §f{current}§e/§f{total} §e{next} §6>>================
amount: 10
format: "{command} §7> {description}"
prev: 上一页
next: 下一页
commands:
action:
command: §e/ni §faction [玩家ID] [动作内容]
description: 执行NI物品动作
edithand:
command: §e/ni §fedithand [玩家ID] [物品编辑函数ID] [函数内容]
description: 通过对应编辑函数编辑主手物品
editoffhand:
command: §e/ni §feditoffhand [玩家ID] [物品编辑函数ID] [函数内容]
description: 通过对应编辑函数编辑副手物品
editslot:
command: §e/ni §feditslot [玩家ID] [物品编辑函数ID] [函数内容]
description: 通过对应编辑函数编辑对应槽位物品
itemNBT:
command: §e/ni §fitemNBT
description: 查看当前手中物品的NBT
list:
command: §e/ni §flist (页码)
description: 查看所有NI物品
get:
command: §e/ni §fget [物品ID] (数量) (是否反复随机) (指向数据)
description: 根据ID获取NI物品
give:
command: §e/ni §fgive [玩家ID] [物品ID] (数量) (是否反复随机) (指向数据)
description: 根据ID给予NI物品
givePack:
command: §e/ni §fgivePack [玩家ID] [物品包ID] (数量)
description: 根据ID给予NI物品包
giveAll:
command: §e/ni §fgiveAll [物品ID] (数量) (是否反复随机) (指向数据)
description: 根据ID给予所有人NI物品
drop:
command: §e/ni §fdrop [物品ID] [数量] [世界名] [X坐标] [Y坐标] [Z坐标] [是否反复随机] [物品解析对象] (指向数据)
description: 于指定位置掉落NI物品
dropPack:
command: §e/ni §fdropPack [物品包ID] [数量] [世界名] [X坐标] [Y坐标] [Z坐标] [物品解析对象]
description: 于指定位置掉落NI物品包
save:
command: §e/ni §fsave [物品ID] (保存路径)
description: 将手中物品以对应ID保存至对应路径
cover:
command: §e/ni §fcover [物品ID] (保存路径)
description: 将手中物品以对应ID覆盖至对应路径
mm load:
command: §e/ni §fmm load [物品ID] (保存路径)
description: 将对应ID的MM物品保存为NI物品
mm cover:
command: §e/ni §fmm cover [物品ID] (保存路径)
description: 将对应ID的MM物品覆盖为NI物品
mm loadAll:
command: §e/ni §fmm loadAll (保存路径)
description: 将全部MM物品转化为NI物品
mm get:
command: §e/ni §fmm get [物品ID] (数量)
description: 根据ID获取MM物品
mm give:
command: §e/ni §fmm give [玩家ID] [物品ID] (数量)
description: 根据ID给予MM物品
mm giveAll:
command: §e/ni §fmm giveAll [物品ID] (数量)
description: 根据ID给予所有人MM物品
reload:
command: §e/ni §freload
description: 重新加载NI物品
help:
command: §e/ni §fhelp
description: 查看帮助信息
# 物品列表格式
ItemList:
Prefix: §6===========§eNeigeItems§6===========
Suffix: §6======<< §e{prev} §f{current}§e/§f{total} §e{next} §6>>======
ItemAmount: 10
ItemFormat: §6{index}. §a{ID} §6- §f{name}
Prev: 上一页
Next: 下一页
# 物品拥有者提示信息显示方式
ItemOwner:
# 通过/ni get及/ni give获取物品时, 移除物品上的拥有者标签
removeNBTWhenGive: false
# actionbar / message
messageType: actionbar
# 掉落物颜色实现方式(protocol对应protocollib发包, vanilla为原版实现)
ItemColor:
# protocol / vanilla
type: protocol
ItemAction:
# 是否将1.6以下版本的ItemAction配置转换为1.7版本格式
upgrade: true
# 连击间隔(ms)
comboInterval: 500

GlobalSections/ExampleSection.yml

global-strings-1:
# 随机字符节点
type: strings
values:
- test1
- test2
global-number-1:
# 随机数节点
type: number
# 随机数最小值
min: 1
# 随机数最大值
max: 2
# 小数保留位数
fixed: 3
global-calculation-1:
# 公式节点
type: calculation
# 计算公式
formula: 1+2+3<global-number-1>
# 公式结果最小值
min: 1
# 公式结果最大值
max: 100
# 小数保留位数
fixed: 3
global-weight-1:
# 权重字符串节点
type: weight
values:
# 权重::字符串内容
- 5::第一行
- 1::第二行
global-js-1:
# JavaScript节点
type: js
# 脚本路径
path: ExampleScript.js::main

Items/ExampleItem.yml

ExampleItem:
# 物品材质
material: LEATHER_HELMET
# 物品CustomModelData(适用于1.14+)
custommodeldata: 1
# 物品损伤值
damage: 1
# 物品名
name: §6一件皮革甲
# 物品Lore
lore:
- 'PAPI变量测试: %player_level%'
- '16进制颜色测试: <#ABCDEF>好耶'
- '私有简单节点测试: <simple-1>'
- '私有字符串节点测试: <strings-1>'
- '私有随机数节点测试: <number-1>'
- '私有公式节点测试: <calculation-1>'
- '私有权重节点测试: <weight-1>'
- '私有JavaScript节点测试: <js-1>'
- '即时声明字符串节点测试: <strings::number-1_weight-1>'
- '即时声明随机数节点测试: <number::0_10_0>'
- '即时声明公式节点测试: <calculation::1+1+3+<number-1>_2>'
- '即时声明权重节点测试: <weight::5::权重文本1_1::权重文本2>'
- '即时声明papi节点测试: <papi::<papiString-1><papiString-2>>'
- '即时声明JavaScript节点测试: <js::ExampleScript.js::main>'
- '全局节点调用测试: <global-strings-1>'
- '嵌套识别测试: <<strings-1>>'
- '文本中小于号请添加反斜杠, 防止错误识别'
- '形如: \<\<\<\>\>\>'
- '请尽量避免使用即时声明节点'
- "换行符测试\n换行符测试"
# 物品附魔
enchantments:
ARROW_DAMAGE: 1
ARROW_KNOCKBACK: 1
# 物品隐藏标识
hideflags:
- HIDE_ATTRIBUTES
- HIDE_DESTROYS
# 物品颜色(适用于药水/皮革装备)
color: 65535
# 额外选项
options:
charge: 10
color: GOLD
# 物品NBT
nbt:
# NBT中也可以随机调用节点
<strings::文本1_文本2_文本3_文本4>: 114514
# 可以在NBT中编辑物品的原版属性
AttributeModifiers:
- Amount: 10
AttributeName: minecraft:generic.max_health
Operation: 0
UUID:
- 0
- 31453
- 0
- 59664
Name: generic.maxHealth
# 引用的全局节点
globalsections:
# 这种直接填写文件名的方式可以直接调用文件内的全部全局节点
# - ExampleSection.yml
- global-strings-1
- global-number-1
# 物品私有节点
sections:
simple-1: <strings::text1_text2_text3>
strings-1:
type: strings
values:
- 测试文本1
- 测试文本2
number-1:
type: number
min: 1
max: 2
fixed: 3
calculation-1:
type: calculation
formula: 1+2+3<number-1>+<number-1>
min: 1
max: 100
fixed: 3
weight-1:
type: weight
values:
- 5::第一行
- 1::第二行
js-1:
type: js
path: ExampleScript.js::main
papiString-1:
type: strings
values:
- "player_"
papiString-2:
type: strings
values:
- "name"
ExampleItem2:
material: STONE
ExampleItem3:
material: STONE
ExampleItem4:
material: STONE
name: "&f%neigeitems_nbt_NeigeItems.id%"
lore:
- '&f物品使用次数: %neigeitems_charge%/%neigeitems_maxCharge%'
options:
charge: 10

# Check节点测试
CheckTest:
material: STONE
name: <check>
sections:
# 待检查的节点, 随机返回test1, test2, test3中的一个值
test:
type: strings
values:
- test1
- test2
- test3
check:
type: check
# 待检查的值
value: <test>
# 执行动作
# 条件中默认导入了value
actions:
# 如果value为test1
- condition: value == "test1"
# 通知玩家
actions:
- "tell: 你得到了名为 test1 的物品"
# value不为test1
deny:
# value为test2
condition: value == "test2"
# 通知玩家
actions:
- "tell: 你得到了名为 test2 的物品"
# value不为test2
deny:
# value为test3
condition: value == "test3"
# 通知玩家
actions:
- "tell: 你得到了名为 test3 的物品"

WhenTest:
material: STONE
name: <test> - <when>
sections:
test: <number::0_100>
when:
type: when
value: <test>
conditions:
- condition: value < 10
result: E
- condition: value < 30
result: D
- condition: value < 50
result: C
- condition: value < 70
result: B
- condition: value < 90
result: A
- condition: value <= 100
result: S

ComboTest:
material: DIAMOND

# 一个测试模板
template1:
material: IRON_SWORD
lore:
- "&e攻击伤害: &f<damage>"
nbt:
MMOITEMS_ATTACK_DAMAGE: (Double) <damage>
# 一个测试模板
template2:
material: DIAMOND_SWORD

# 一个全局继承测试, 它继承了"template1"的所有内容
templateItem1:
inherit: template1
name: §f物品继承测试
sections:
damage: 100
# 一个部分继承测试, 它继承了"template1"的lore, 以及"template2"的material
templateItem2:
inherit:
lore: template1
material: template2
name: §f物品继承测试
sections:
damage: 100
# 一个顺序继承测试, 它将按顺序进行节点继承. 先继承"template1"的所有内容,再继承"template2"的所有内容
templateItem3:
inherit:
- template1
- template2
name: §f物品继承测试
sections:
damage: 100

inheritSectionTest:
material: STONE
lore:
- <templateTest>
- <inheritTest>
- <inherit::templateTest>
sections:
templateTest: <strings::text1_text2_text3>
inheritTest:
type: inherit
template: templateTest
actionTest:
material: STONE
name: <test>
nbt:
test1: "666"
test2:
test3: "777"
test4:
- "888"
- "999"
sections:
test: "yeah"
customSection:
material: STONE
lore:
- '自定义节点测试: <test-1>'
- '自定义节点测试: <test::test_test_test>'
sections:
test-1:
type: test
values:
- test
- test
- test
- test
eatTest:
material: APPLE
eatTest2:
material: APPLE
options:
charge: 10
dropTest:
material: STONE
dropTest2:
material: STONE
options:
charge: 3
ownerTest:
material: STONE
name: 你捡我啊
options:
# 通过/ni drop或击杀MM怪物掉落该物品, 该物品首次拾取只能由Neige完成
# 你可以在此处填写"%player_name%", 这样就是谁击杀就属于谁了
# 首次拾取后将不再有掉落物归属效果
# 服务器重启后效果重置(掉了, 关服了, 再次开服, 谁都能捡)
owner: Neige
CustomAction:
all:
- "test"

# 物品时限测试
itemTimeTest:
material: STONE
name: 限时物品-到期时间-<js::ItemTime.js::main_<itemtime>>
options:
itemtime: <itemtime>
sections:
itemtime: 60

# join节点测试
JoinTest1:
material: STONE
lore:
# 结果: 1, 2, 3, 4, 5
- 'join节点: <test>'
sections:
test:
type: join
# 待操作的列表
list:
- 1
- 2
- 3
- 4
- 5
JoinTest2:
material: STONE
lore:
# 结果: 1-2-3-4-5
- 'join节点: <test>'
sections:
test:
type: join
list:
- 1
- 2
- 3
- 4
- 5
# 分隔符(默认为", )
separator: "-"
JoinTest3:
material: STONE
lore:
# 结果: <1, 2, 3, 4, 5>
- 'join节点: <test>'
sections:
test:
type: join
list:
- 1
- 2
- 3
- 4
- 5
# 前缀
prefix: "<"
# 后缀
postfix: ">"
JoinTest4:
material: STONE
lore:
# 结果: 1, 2, 3
- 'join节点: <test>'
sections:
test:
type: join
list:
- 1
- 2
- 3
- 4
- 5
# 限制长度
limit: 3
JoinTest5:
material: STONE
lore:
# 结果: 1, 2, 3, ...
- 'join节点: <test>'
sections:
test:
type: join
list:
- 1
- 2
- 3
- 4
- 5
limit: 3
# 超过长度的部分用该符号代替
truncated: "..."
JoinTest6:
material: STONE
lore:
# 结果: 2, 3, 4, 5, 6
- 'join节点: <test>'
sections:
test:
type: join
list:
- 1
- 2
- 3
- 4
- 5
# 对列表中的每个元素进行一定操作
# this.it代表当前元素
# this.index代表当前序号(0代表第一个, 1代表第二个, 以此类推)
# this.player代表玩家
# this.vars(String string)用于解析节点
# List<String> this.list代表节点中的list
transform: |-
// 尝试将当前元素转换为整数, 并加一, 然后保留整数
return (parseInt(this.it) + 1).toFixed(0)
JoinTest7:
material: STONE
lore:
# 等同于:
# - 第一行
# - 第二行
# - 第三行
#
# 这个节点应该单独占据一行
# 不要在这行写其他文本(比如'join节点: <test>')
# 具体请自行测试
- '<test>'
sections:
test:
type: join
list:
- 第一行
- 第二行
- 第三行
# 像下面这样写分隔符、前缀和后缀
# 即可达到调用多行lore的效果
separator: "\\n"
prefix: '"'
postfix: '"'

GaussianTest:
material: STONE
lore:
- '随机数: <test>'
# <gaussian::基础数值_浮动单位_浮动范围上限_取整位数(默认为1, 可省略)_数值下限(可省略)_数值上限(可省略)>
- '随机数: <gaussian::100_0.1_0.5_1>'
sections:
test:
type: gaussian
# 基础数值
base: 100
# 浮动单位
spread: 0.1
# 浮动范围上限
maxSpread: 0.5
# 取整位数(默认为1)
fixed: 1
# 数值下限
min: 0
# 数值上限
max: 10000

# 不使用js的操作形式
RepeatTest1:
material: STONE
lore:
# 结果: 形似&4||||||||||||||&f||||||, &f出现的位置随机
- 'repeat节点: &4<repeat1>&f<repeat2>'
sections:
repeat1:
type: repeat
content: "|"
repeat: <number>
repeat2:
type: repeat
content: "|"
repeat: <calculation::20-<number>>
number:
type: number
min: 0
max: 20
fixed: 0
# 使用js的操作形式
RepeatTest2:
material: STONE
lore:
# 结果: 形似&4||||||||||||||&f||||||, &f出现的位置随机
- 'repeat节点: <repeat>'
sections:
repeat:
type: repeat
content: "|"
repeat: 20
prefix: "§4"
# 对列表中的每个元素进行一定操作
# this.it代表content
# this.index代表当前序号(0代表第一个, 1代表第二个, 以此类推)
# this.player代表玩家
# this.vars(String string)用于解析节点
transform: |-
if (this.index == this.vars("<number>")) {
return "§f" + this.it
} else {
return this.it
}
number:
type: number
min: 0
max: 20
fixed: 0
RepeatTest3:
material: STONE
lore:
# 随机1-4行"&4&l<红宝石槽>"
- '<repeat>'
sections:
repeat:
type: repeat
content: '&4&l<红宝石槽>'
repeat: <number::1_4_0>
# 像下面这样写分隔符、前缀和后缀
# 即可达到调用多行lore的效果
separator: "\\n"
prefix: '"'
postfix: '"'
RepeatTest4:
material: STONE
lore:
# 形似"§4§l<★>-§4§l<★>-§4§l<★>", 随机1-4个
- '<repeat>'
sections:
repeat:
type: repeat
content: '§4§l<★>'
repeat: <number::1_4_0>
separator: "-"

Scripts/ExampleScript.js

function main() {
if (typeof this.player != "undefined") {
return this.vars("<strings-1>") + this.player.getName()
} else {
return this.vars("<strings-1>")
}
}

ItemActions/ExampleAction.yml

ExampleItem2:
# 左键触发
left:
# 动作内容
actions:
# 这条动作没有condition, 所以必定执行
- "tell: 你正尝试触发&e ExampleItem2 &f物品"
# 当前这条动作的执行条件
- condition: perm("item.ExampleItem2")
# 满足条件后执行的动作
actions:
# 后台执行
- "console: say &e%player_name% &f拥有&e item.ExampleItem2 &f权限"
# 玩家执行
- "command: say 我拥有&e item.ExampleItem2 &f权限"
# 不满足条件时执行的动作
deny:
- "tell: 你没有&e item.ExampleItem2 &f权限"
# 一句话概括: 不想看的话, 优先使用"sync", 别用"actions"
#
# 从实际功能而言, “sync”与"actions"没有区别.
# 区别在于, "sync"下的所有内容都是同步解析, 同步触发的
#
# 即: 所有非线程安全的行为都应该在"sync"下进行
# 比如: 检测玩家是否拥有某个物品, 然后通过指令扣除
# 模拟情境: 你将A物品配置为"满足 papi("%checkitem_amount_mat:stone%") >= 1 时, 扣除一个石头, 给予100元"
# 如果你将这些动作配置到"actions"下, 那么可能出现:
# 判断玩家确实拥有大于等于1个石头, 然后玩家将石头丢出背包
# 后面扣除石头时, 因为玩家没有足够的石头, 扣除操作相当于失效
# 之后给予100元的行为却仍然执行, 玩家就成功在不消耗石头的情况下获得了100元
# 因此这些行为应该配置于"sync"下, 而非"actions"
#
# 注: "sync"下所有动作同步触发, 但这不代表"actions"下所有内容异步触发.
# 所有基础物品动作都作了相关判断, 比如takeHealth, takeFood, takeLevel等行为,
# 都会挪到主线程实施, 避免出现线程安全问题
sync:
- "tell: 你好, 这条消息通过主线程发送"
ExampleItem3:
# 左键触发
left:
# 冷却时间(单位是ms)
cooldown: 3000
# 冷却组, 同一冷却组的物品共享冷却时间
group: test2
# 消耗选项
consume:
# 物品消耗条件
condition: perm("item.ExampleItem3")
# 每次消耗物品数量
amount: 1
# 不满足条件时执行的动作
deny:
- "tell: 你没有&e item.ExampleItem3 &f权限"
# 动作内容
actions:
# 这条动作没有condition, 所以必定执行
- "tell: 你正尝试触发&e ExampleItem3 &f物品"
ExampleItem4:
all:
consume:
amount: 1
sync:
- 'console: say He''s name is %player_name%'
- 'command: say My name is %player_name%'
ActionTest:
all:
sync:
# 检测test1这条NBT的值是否等于"666"
condition: parseItem("<nbt::test1>") == "666"
actions:
- 'console: say 名为test1的NBT的值为: <nbt::test1>'
- 'console: say 名为test2.test3的NBT的值为: <nbt::test2.test3>'
- 'console: say 名为test4.0的NBT的值为: <nbt::test4.0>'
- 'console: say 名为test4.1的NBT的值为: <nbt::test4.1>'
- 'console: say 名为test的节点的值为: <data::test>'
- 'console: say 随机数尝试: <number::0_10_2>'
EatTest1:
eat:
sync:
- 'giveFood: 5'
- 'giveHealth: 5'
EatTest2:
eat:
consume:
amount: 1
sync:
- 'giveFood: 5'
- 'giveHealth: 5'
DropTest1:
drop:
actions:
- 'castSkill: SkillTest'
DropTest2:
drop:
consume:
amount: 1
actions:
- 'castSkill: SkillTest'
CustomAction:
all:
sync:
- test
ComboTest:
left:
sync:
# 在ComboTest组记录, 触发了类型为left的连击
- "combo: ComboTest left"
# 检测ComboTest组是否完成了left-right-left连击
- condition: combo("ComboTest", ["left", "right", "left"])
actions:
# 进行对应操作
- 'tell: &e连击 &bL &f+ &bR &f+ &bL'
# 已达成最终需要的连击, 清空ComboTest组的连击记录
- 'comboClear: ComboTest'
deny:
# 检测ComboTest组是否完成了left连击
condition: combo("ComboTest", ["left"])
actions:
# 进行对应操作
- 'tell: &e连击 &bL'
right:
sync:
# 在ComboTest组记录, 触发了类型为right的连击
- "combo: ComboTest right"
# 检测ComboTest组是否完成了left-right连击
- condition: combo("ComboTest", ["left", "right"])
actions:
# 进行对应操作
- 'tell: &e连击 &bL &f+ &bR'

CustomSection/CustomSection.js

// 文件名不重要, 写成啥都行
// main函数会自动执行
function main() {
// 导入相应的类, 这两行看不懂的话直接抄就行
const SectionManager = Packages.pers.neige.neigeitems.manager.SectionManager.INSTANCE
const CustomSection = Packages.pers.neige.neigeitems.section.impl.CustomSection
const SectionUtils = Packages.pers.neige.neigeitems.utils.SectionUtils

// 创建自定义节点
const customSection = new CustomSection(
// 节点id
"test",
/**
* 用于私有节点解析
* @param data ConfigurationSection 节点内容
* @param cache HashMap<String, String>? 解析值缓存
* @param player OfflinePlayer? 待解析玩家
* @param sections ConfigurationSection? 节点池
* @return 解析值
*/
function(data, cache, player, sections) {
if (data.contains("values")) {
// SectionUtils.parseSection("待解析字符串", cache, player, sections)用于解析节点内容
return SectionUtils.parseSection("<number::0_1_2>", cache, player, sections)
}
return null
},
/**
* 用于即时节点解析
* @param args List<String> 节点参数
* @param cache HashMap<String, String>? 解析值缓存
* @param player OfflinePlayer? 待解析玩家
* @param sections ConfigurationSection? 节点池
* @return 解析值
*/
function(args, cache, player, sections) {
return SectionUtils.parseSection("<number::0_1_2>", cache, player, sections)
})
// 节点注册
SectionManager.loadParser(customSection)
}

CustomActions/CustomAction.js

// 文件名不重要, 写成啥都行
// main函数会自动执行
function main() {
// 导入相应的类, 这两行看不懂的话直接抄就行
const ActionManager = Packages.pers.neige.neigeitems.manager.ActionManager.INSTANCE
const SectionUtils = Packages.pers.neige.neigeitems.utils.SectionUtils

// 插入新的自定义动作
ActionManager.addAction(
// 动作名称
"test",
// 动作内容(一般是异步调用的, 所以需要同步执行的内容需要自行同步)
function(player, string) {
// 调用动作
ActionManager.runAction(player, "tell: 123")
ActionManager.runAction(player, "tell: 456")
player.sendMessage(SectionUtils.parseSection("<number::0_10_2>"))
// 每个动作都一定要返回一个布尔量(true或false), 返回false相当于终止一连串动作的执行
return true
})
}

CustomItemEditors/CustomItemEditor.js

// 文件名不重要, 写成啥都行
// main函数会自动执行
function main() {
// 导入相应的类, 这两行看不懂的话直接抄就行
const ItemEditorManager = Packages.pers.neige.neigeitems.manager.ItemEditorManager.INSTANCE

// 这是我写这段代码用到的类, 不是每次添加自定义物品编辑函数都要用到
const ArrayList = Packages.java.util.ArrayList
const ChatColor = Packages.org.bukkit.ChatColor
const Material = Packages.org.bukkit.Material

// 添加自定义物品编辑函数
// 这里我添加了一个名为"test"的物品编辑函数, 但实际上它的功能与addLore函数相同
ItemEditorManager.addItemEditor(
// 函数名
"test",
/**
* 物品编辑函数
* @param player Player 物品拥有者
* @param itemStack ItemStack 待编辑物品
* @param content String 传入的文本
*/
function(player, itemStack, content) {
// 判断是不是空气
if (itemStack.type != Material.AIR) {
// 获取itemMeta
const itemMeta = itemStack.itemMeta
if (itemMeta != null) {
// 获取并设置lore
let lore = itemMeta.lore
if (lore == null) lore = new ArrayList()
lore.addAll(ChatColor.translateAlternateColorCodes('&', content).split("\\n"))
itemMeta.lore = lore
// 将改动完成的itemMeta设置回去
itemStack.setItemMeta(itemMeta)
// 物品编辑都需要返回一个布尔量, 判断你是否编辑成功
return true
}
}
// 物品编辑都需要返回一个布尔量, 判断你是否编辑成功
return false
}
)
}

ItemPacks/ExampleItemPack.yml

Example1:
Items:
# 支持解析即时声明节点
# [物品ID] (数量(或随机最小数量-随机最大数量)) (生成概率) (是否反复随机) (指向数据)
- ExampleItem 1-5 0.5
- test
FancyDrop:
# 偏移量
offset:
# 横向偏移量(或随机最小偏移量-随机最大偏移量)
x: 0.1
# 纵向偏移量(或随机最小偏移量-随机最大偏移量)
y: 0.8
angle:
# 抛射类型(round/random)
type: round
Example2:
Items:
- <test>
FancyDrop:
offset:
x: 0.1
y: 0.8
angle:
type: round
# 引用的全局节点
globalsections:
# 这种直接填写文件名的方式可以直接调用文件内的全部全局节点
# - ExampleSection.yml
- global-strings-1
- global-number-1
# 物品私有节点
sections:
test:
type: strings
values:
- ExampleItem 5 1
- ExampleItem 10 1

Scripts/ItemTime.js

function main(time) {
const date = new Date()
date.setTime(date.getTime() + (Number(time) * 1000))
return date.getFullYear() + "年" + (date.getMonth() + 1) + "月" + date.getDate() + "日" + date.getHours() + "时" + date.getMinutes() + "分" + date.getSeconds() + "秒"
}