常见问题与边缘情况
遇到报错 / 行为不符合预期时,先翻这一页。
语法错误
| 错误 | 原因 | 解决 |
|---|---|---|
| YAML 解析失败 | 缩进不正确 | 检查空格,不要混用 Tab |
| 字符串未闭合 | 引号不匹配 | 确保引号成对 |
| 变量未定义 | 拼写错误或顺序错误 | 检查变量名,先定义后使用 |
mapping values are not allowed here | 槽位定义中的冒号被 YAML 当成映射分隔符 | 见下方 引号嵌套规则 |
| if 块内代码不执行 | 使用了单行 if 语法 | 见下方 流程控制必须多行 |
槽位定义的 YAML 引号嵌套规则
当槽位定义中的 lore、name 等参数包含冒号 : 时,YAML 会把它当成映射分隔符,导致解析失败。
错误示例:
yaml
slots:
# ✗ lore 中的冒号导致 YAML 解析失败
信: display(id=信息, material=BOOK, name="&e信息", lore="&7状态: 待机|&7等级: 1")
# ↑ 这里被当成映射分隔符正确写法:
yaml
slots:
# ✓ 外层单引号,内层字符串用双引号,表达式内字符串用两个单引号转义
'信': 'display(id=信息, material=BOOK, name="&e信息", lore="&7状态: 待机|&7等级: 1")'
# ✓ 外层双引号,内层用单引号
'火': "button(id=开始, material=MAGMA_CREAM, name='&c&l点火', lore='&7点击开始|&7冷却: 10秒')"
# ✓ match 表达式里需要字符串字面量时,用两个单引号 '' 转义
'A': 'input(id=材料1, match="lore.contains(''丹材'')", placeholder=STAINED_GLASS_PANE:12:&8丹材)'规则总结:
| 外层引号 | 内层字符串 | 表达式内字符串 |
|---|---|---|
单引号 '...' | 双引号 "..." | 两个单引号 '' |
双引号 "..." | 单引号 '...' | 单引号 '...' |
中文槽位键(如
信、火、丹)也建议用单引号包裹,避免部分 YAML 解析器的兼容问题。
流程控制必须使用多行格式
IM 脚本引擎不支持单行流程控制,所有 if、for、while(注意 while 本身未实现)都必须换行。
yaml
variables: |
# ✗ 单行 if 不会执行!
if @input.filled { 数量 += 1 }
if a == 1 { x = 10 }
# ✓ 必须多行
if @input.filled {
数量 += 1
}
if a == 1 {
x = 10
}
# ✓ else if 也必须多行
if a == 1 {
x = 10
} else if a == 2 {
x = 20
} else {
x = 30
}实测:
if 条件 { 变量 = 值 }这种单行写法会导致块内代码不会执行,也不报错。
空值处理
# ✗ 直接使用可能为空的值
攻击力 = @input.attr("攻击力") # 没有此属性时返回 0(或 null,视实现)
# ✓ 使用默认值
攻击力 = ifnull(@input.attr("攻击力"), 0)
# ✓ 先判断槽位是否有物品
if @input.filled {
// 安全使用 @input
}类型转换
# 字符串拼接
消息 = "等级: " + 等级 # ✓
# 数值计算
总和 = a + b # ✓ 确保 a 和 b 都是数字
# 布尔判断
if 等级 >= 5 # ✓
if "等级" >= 5 # ✗ 字符串被当字面量比较lore.replace 常见问题
yaml
# 问题:变量没有替换
# ✗ 两参数写法会被当作模板语法
装备.lore.replace("等级: {旧}", "等级: {新}")
# ✓ 写法 1:三参数
装备.lore.replace("等级", "{旧}", "{新}")
# ✓ 写法 2:模板语法用 {_} 占位
装备.lore.replace("等级: {_}", "等级: {新}")详见 Lore 动作。
作用域问题
yaml
# for 仅支持数值范围,不支持列表遍历
# 累加槽位组属性,用 sum_attr 而不是手动循环:
total = sum_attr(@food, "攻击力")
effect.message("总计: {total}")
# for 循环外定义的变量,块内修改在外部可见
count = 0
for i in 1..5 {
count += 1
}
effect.message("计数: {count}") # 输出 5预览脚本有独立的作用域陷阱,见 预览模式。
GUI 会话与物品安全
物品归还机制
| 场景 | 处理方式 | 状态 |
|---|---|---|
| 玩家正常关闭 GUI | 直接归还到背包 | ✅ |
| GUI 进入后台模式超时 | 在线时归还,离线时保存到文件 | ✅ |
| 玩家下线(后台模式) | 保存到文件,上线后恢复会话 | ✅ |
| 玩家下线(非后台模式) | 尝试归还,失败则保存到文件 | ✅ |
服务器正常关闭 (stop) | 保存所有有物品的会话到文件 | ✅ |
服务器崩溃(kill -9) | ⚠️ 物品可能丢失 | 未处理 |
离线会话存储
- 位置:
plugins/ItemMaster/offline-sessions/{玩家UUID}.yml - 内容:GUI ID、所有槽位物品(Base64 序列化)、变量快照、Toggle 状态、锁定槽位列表、保存时间戳
- 过期:使用
session_timeout;非后台模式保存时默认设 1 小时过期;-1永不过期
服务器崩溃
onDisable不会被调用,内存中的物品丢失。- 缓解:重要物品先
vault.store存到物品库。
物品序列化失败
使用 BukkitObjectOutputStream,以下情况可能失败:
- 模组物品(非原版 Minecraft 物品)
- 跨 MC 版本不兼容(1.12 保存 → 1.20 读取)
- 特殊 NBT 数据(某些插件的自定义序列化器未注册)
原版物品和大多数插件物品都能正常序列化。
BungeeCord / Velocity 跨服
- 会话仅存在于当前服务器。
- 玩家切服触发正常下线流程,物品会被保存到当前服的离线会话。
- 不支持跨服会话同步(已在更新计划中)。
- 跨服传物品用 Vault 物品存储 + 数据库 / Redis 自行同步 ID。
详见 会话与物品安全。