新映射 LyGalaxyMapped
LyGalaxyMapped 是一个服务端动态构筑插件。插件根据装备、玩家状态、权限、PlaceholderAPI 条件和临时标签计算标签层数,再按照映射需求、排斥条件和组优先级选择生效构筑,最后刷新属性、药水效果和状态消息。
插件版本为 1.0.0。属性写入需要配置并启用对应的属性插件;PlaceholderAPI 为可选接入,只有使用 PAPI 条件、插件占位符、消息占位符或公式占位符时才需要安装。
项目概览
| 项目 | 说明 |
|---|---|
| 发布类型 | 服务端插件 |
| 当前版本 | 1.0.0 |
| 主要玩法 | 装备、玩家状态和临时标签转换为标签层数,再匹配动态映射构筑 |
| 属性接入 | AttributePlus、AttributeSystem、SX-Attribute、ItemLoreOrigin |
| 主配置 | plugins/LyGalaxyMapped/config.yml |
| 映射配置 | plugins/LyGalaxyMapped/mapped/ 下扩展名为 .yml 的文件 |
| 根指令 | /lgm |
支持版本
项目提供以下 Minecraft 服务端版本的适配代码:
1.7.10、1.8.8、1.11.2、1.12.2、1.13.2、1.14.4、1.15.2、1.16.5、1.17.1、1.18.2、1.19.2、1.19.4、1.20.1、1.20.2、1.20.3。
项目证据未确认未列出版本的兼容性。
依赖与外部接入
属性插件
主配置中的 attribute-plugin 用于选择属性写入方式。需要让映射属性生效时,必须安装并启用配置对应的属性插件。
| 配置值 | 用途与要求 |
|---|---|
AttributePlus | 使用 AttributePlus 写入属性。 |
AttributeSystem | 使用 AttributeSystem 写入属性。 |
SX-Attribute | 使用 SX-Attribute 写入属性。 |
ItemLoreOrigin | 使用 ItemLoreOrigin 写入属性。ItemLoreOrigin 未启动时属性写入不会成功,同步任务固定每 20 tick 运行一次。 |
属性插件名称会去除首尾空格并按不区分大小写处理。配置值不支持或对应接口不可用时,属性不会写入。
PlaceholderAPI
PlaceholderAPI 为可选依赖。以下功能需要 PlaceholderAPI 已安装并启用:
papi(...)标签条件。- LyGalaxyMapped 的 PlaceholderAPI 占位符。
- 映射属性公式中的 PlaceholderAPI 占位符。
- 映射状态消息中的 PlaceholderAPI 占位符展开。
外部背包与槽位
plugin-slot 可以读取原版背包和多个外部背包插件的槽位。使用外部槽位时,对应插件及其槽位 API 必须可用。
支持的外部槽位类型包括 DragonCore、GermPlugin、APInventory、LyInventory、LyInventoryReload 和 YeeJewelry。
插件资源中的 plugin.yml 声明了以下软依赖:PlaceholderAPI、DZ_Status、AttributePlus、SX-Attribute、ItemLoreOrigin、APInventory、LyInventory、GermPlugin。其中 DZ_Status 的具体功能接入,项目证据未作进一步确认。
功能
- 按物品名称、Lore、NBT、权限、PlaceholderAPI 和玩家状态计算标签层数。
- 每条条件独立统计命中次数,并按照数字权重增加标签层数。
- 支持标签层数上限、映射需求和排斥条件。
- 相同映射组只激活满足条件且优先级最高的一条映射。
- 不同映射组可以同时生效。
- 从装备 Lore 提取数值,为映射属性提供动态变量。
- 使用标签层数、Lore 动态变量和 PlaceholderAPI 展开属性公式。
- 为生效映射刷新药水效果。
- 在映射进入、离开或同组切换时发送消息。
- 提供标签、映射状态和映射属性的 PlaceholderAPI 查询。
- 提供临时标签公共 API。
- 支持重载配置,并在重载后重新计算在线玩家状态。
指令
根指令为 /lgm。
| 指令 | 说明 | 执行限制 |
|---|---|---|
/lgm | 显示帮助。 | 无额外限制。 |
/lgm help | 显示帮助。 | 无额外限制。 |
/lgm active [玩家] | 查询自己或指定在线玩家当前已激活的映射。 | 查询其他玩家需要 OP;控制台执行时必须指定在线玩家。 |
/lgm tag [玩家] | 查询自己或指定在线玩家最近计算出的标签及层数。 | 查询其他玩家需要 OP;控制台执行时必须指定在线玩家。 |
/lgm reload | 重载主配置和 mapped 目录中的 .yml 文件,并重新计算在线玩家。 | 仅 OP。 |
plugin.yml 未声明权限节点,权限判断使用发送者的 OP 状态。
active 和 tag 查询读取最近一次计算缓存,不会因为查询命令重新扫描物品。OP 在查询命令的第二个参数输入在线玩家名称时,可以查询目标玩家;普通玩家不会获得其他玩家名称的补全。
配置文件结构
插件使用两个配置范围:
plugins/LyGalaxyMapped/config.yml:运行参数、属性插件和全局槽位。plugins/LyGalaxyMapped/mapped/:标签和映射数据。
tag-check 和 mapped 不从主 config.yml 读取,只从 mapped 目录中的 .yml 文件读取。插件会递归扫描该目录及其子目录,并按文件路径排序加载。相同标签 ID 或映射 ID 重复时,后加载的定义会被忽略。
插件默认保存 mapped/示例配置.yml,不会覆盖已经存在的文件。
主配置:config.yml
yaml
attribute-plugin: 'AttributePlus'
thread-running-interval: 20
plugin-slot:
- 'Origin#MainHand'
- 'Origin#OffHand'
- 'Origin#Helmet'
- 'Origin#ChestPlate'
- 'Origin#Legging'
- 'Origin#Boots'顶层配置键
| 配置键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
attribute-plugin | 字符串 | AttributePlus | 选择属性写入插件。支持 AttributePlus、AttributeSystem、SX-Attribute、ItemLoreOrigin。 |
thread-running-interval | 整数 | 20 | 标签和映射检测间隔,单位为 tick。小于 1 时按 1 处理。 |
plugin-slot | 字符串列表 | 配置文件中的六个原版槽位 | 指定插件读取和扫描的物品槽位。 |
plugin-slot 槽位格式
槽位配置使用完整字符串,# 用于分隔插件类型、背包标识和槽位标识。
| 格式 | 说明 |
|---|---|
Minecraft#槽位ID | 读取原版背包数字槽位,槽位 ID 必须是数字。 |
Origin#MainHand | 原版主手。 |
Origin#OffHand | 原版副手。旧版本没有副手 API 时返回空值。 |
Origin#Helmet | 原版头盔槽位。 |
Origin#ChestPlate | 原版胸甲槽位。 |
Origin#Legging | 原版护腿槽位。 |
Origin#Boots | 原版鞋子槽位。 |
DragonCore#槽位名 | 读取 DragonCore 槽位。 |
GermPlugin#槽位名 | 读取 GermPlugin 槽位。 |
APInventory#分页ID#槽位ID | 读取 APInventory 指定分页的数字槽位。 |
LyInventory#背包ID#槽位名 | 读取 LyInventory 指定背包的槽位。 |
LyInventoryReload#背包ID#槽位名 | 读取 LyInventoryReload 指定背包的槽位。 |
YeeJewelry#背包ID#槽位ID | 读取 YeeJewelry 指定背包的槽位。 |
读取到的物品会保存为独立克隆。单个槽位或外部接口读取失败时只跳过该槽位;主手或副手读取失败时会移除对应旧快照,避免旧属性残留。
标签检测配置:mapped/*.yml
标签配置的顶层节点为 tag-check。
yaml
tag-check:
'火焰':
condition:
1:
- lore('元素:火焰')
- nbt('lgm.element', 'fire')
2:
- permission('lgm.先天霜火圣体')
max-point: -1标签节点
| 配置键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
tag-check.<标签> | 节点 | 无 | 定义一个标签及其计算规则。 |
tag-check.<标签>.condition | 节点或字符串列表 | 无 | 定义条件。标准写法为 权重: 条件列表。 |
tag-check.<标签>.condition.<权重> | 字符串列表 | 无 | 每条条件独立统计命中次数,每次命中增加对应权重的标签层数。 |
tag-check.<标签>.check-slot | 字符串列表,可选 | 使用全局 plugin-slot | 指定当前标签扫描的槽位。 |
tag-check.<标签>.max-point | 整数 | -1 | 限制最终标签层数。负数表示不限制。 |
tag-check.<标签>.point | 整数,可选 | 1 | 当 condition 直接写成字符串列表时,指定每次命中的层数。 |
同一权重下的多条条件不是多行 AND。每条字符串条件分别统计命中次数,再乘以该条件的权重后累计。同一件物品同时满足多条条件时,各条件仍然分别计数,不进行物品去重。
包含 name、lore 或 nbt 的条件表达式,会在配置槽位范围内按符合条件的物品快照数量统计。只包含权限、PlaceholderAPI 或玩家状态函数的条件,每条条件只按结果命中一次,不会按物品槽位重复计算。
max-point 会在所有条件累计完成后限制最终层数。-1 表示无上限。
直接列表写法
当 condition 不是节点而是字符串列表时,可以使用 point 指定统一权重:
yaml
tag-check:
'白天':
condition:
- time('day')
point: 1
max-point: 1条件表达式
条件使用函数式写法。函数参数使用单引号,多个参数使用逗号分隔。单条条件中的顶层 || 表示 OR;在函数前添加 ! 表示取反。&& 仅用于 papi(...) 的比较表达式。
| 条件 | 说明 |
|---|---|
name('文本') | 物品名称包含文本。 |
name('文本', contains) | 物品名称包含文本。 |
name('文本', equals) | 物品名称完整匹配文本。 |
lore('文本') | 任意一行 Lore 包含文本。 |
lore('文本', contains) | 任意一行 Lore 包含文本。 |
lore('文本', equals) | 任意一行 Lore 完整匹配文本。 |
nbt('路径', '值') | NBT 标量值完整匹配。 |
nbt('路径', 5) | NBT 数值完整匹配。 |
permission('权限节点') | 玩家拥有指定权限时命中。 |
nopermission('权限节点') | 玩家没有指定权限时命中。 |
papi(比较表达式) | 根据 PlaceholderAPI 展开的比较表达式判断。 |
world('世界名') | 玩家当前世界名称匹配时命中。 |
time('day') | 当前世界时间为白天,即 0 到 11999。 |
time('night') | 当前世界时间为夜晚,即 12000 到 23999。 |
gamemode('模式') | 玩家当前游戏模式匹配时命中。 |
weather('clear') | 当前世界无雨且无雷。 |
weather('rain') | 当前世界下雨但不打雷。 |
weather('thunder') | 当前世界正在打雷。 |
weather('storm') | thunder 的同义写法。 |
名称和 Lore 条件的文本参数会先转换 & 颜色码,再进行匹配。
NBT 比较模式
nbt 的字符串比较支持:
equals:完整匹配。!=:不等于。contains:包含目标文本。startsWith:以目标文本开头。endsWith:以目标文本结尾。ignoreCase:忽略英文大小写,可以与其他比较模式组合使用。
NBT 数值比较支持 >、>=、< 和 <=。数值比较要求 NBT 实际值和目标值都可以转换为数字。
示例:
yaml
condition:
1:
- papi(%player_level% >= 5 && %player_level% <= 10)
- permission('lgm.vip') || papi(%player_level% >= 30)
- "!lore('已绑定')"当前格式不读取旧版的 check、attribute-group、lore:{...}、nbt:{...} 或 permission:{...} 写法。
映射配置:mapped/*.yml
映射配置的顶层节点为 mapped。
yaml
mapped:
'霜火共鸣1级':
group-id: '霜火共鸣'
group-priority: 1
require:
'火焰': 1
'冰霜': 1
exclude:
'夜间': 1
lore-get-placeholder:
'变量id': '获得 <value>x玩家 等级点攻击力'
attribute:
- '火属性伤害: {var.变量id}'
- '火焰层数伤害: <{tag.火焰}*2>'
potion:
- 'SPEED:1'
start-message:
- '&7你触发了 &a{id}'
end-message:
- '&7你的 &a{id} &7消失了'映射节点
| 配置键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
mapped.<映射>.group-id | 字符串 | 当前映射 ID | 映射所属的组。同组映射只生效一条。 |
mapped.<映射>.group-priority | 整数 | 0 | 同组映射优先级。满足需求时优先级最高者生效。 |
mapped.<映射>.require | 节点 | 空 | 标签 ID 到最低层数的映射。多个标签必须同时满足。 |
mapped.<映射>.exclude | 节点 | 空 | 标签 ID 到排斥层数的映射。任意标签达到配置层数时,映射不生效。 |
mapped.<映射>.attribute | 字符串列表 | 空列表 | 映射生效时提交给属性插件的属性文本。 |
mapped.<映射>.lore-get-placeholder | 节点 | 空 | 从配置槽位物品的 Lore 中提取动态数值。 |
mapped.<映射>.potion | 字符串列表 | 空列表 | 映射生效时应用的药水效果。 |
mapped.<映射>.start-message | 字符串列表 | 空列表 | 映射开始生效时发送的消息。 |
mapped.<映射>.end-message | 字符串列表 | 空列表 | 映射结束生效时发送的消息。 |
require 中的多个标签默认使用 AND 关系。exclude 中任意标签达到配置层数,当前映射都会被排斥。
相同 group-id 的映射只保留一条:先筛选满足 require 且未触发 exclude 的映射,再选择 group-priority 最高者。同组优先级相同时,映射 ID 按字典序较小者优先。不同 group-id 的映射可以同时生效。
药水格式
药水配置格式为 TYPE:LEVEL[:SECONDS]。
TYPE使用 Bukkit 药水效果名称。LEVEL按游戏显示等级填写,1对应一级效果。SECONDS可选,单位为秒,必须是正整数。- 未填写持续时间或持续时间无效时,默认使用检测间隔的两倍,并且默认值至少为
2秒。 - 单行配置格式错误或效果类型无法识别时,跳过该行。
- 同一类型药水同时来自多个映射时,等级更高者优先;等级相同时持续时间更长者优先。
示例资源中列出的效果名称包括:
SPEED、FAST_DIGGING、SLOW_DIGGING、INCREASE_DAMAGE、HEAL、HARM、JUMP、CONFUSION、REGENERATION、DAMAGE_RESISTANCE、FIRE_RESISTANCE、WATER_BREATHING、INVISIBILITY、BLINDNESS、NIGHT_VISION、HUNGER、WEAKNESS、POISON、WITHER、HEALTH_BOOST、ABSORPTION、SATURATION、FIRE。
映射消息
start-message 和 end-message 只在映射组状态发生变化时发送,不会在每次检测时重复发送。
{id}替换为当前映射 ID。&转换为 Minecraft 颜色码。- PlaceholderAPI 启用时,消息会继续展开 PlaceholderAPI 占位符。
- 同组映射切换时,先发送旧映射的结束消息,再发送新映射的开始消息。
变量与属性公式
Lore 动态变量
lore-get-placeholder 的键是变量名,值是 Lore 模板。使用 <value> 标记待提取的数值位置:
yaml
lore-get-placeholder:
'变量id': '获得 <value>x玩家 等级点攻击力'插件会扫描配置槽位中物品的每一行 Lore,将匹配到的数值累加。同一变量在多个物品或多行 Lore 中命中时会继续累加,未命中的变量按 0 处理。
属性中使用 {var.变量名} 读取 Lore 动态变量。
标签变量
属性中使用 {tag.标签名} 读取本次计算得到的标签层数。装备条件标签和临时标签会合并计算,未找到的标签按 0 处理。
属性公式
属性文本中的 <...> 会被逐段计算。公式支持整数、浮点数、+、-、*、/ 和括号运算。PlaceholderAPI 启用时,公式中的 PlaceholderAPI 占位符会先展开。
yaml
attribute:
- '火焰层数伤害: <{tag.火焰}*2>'
- '等级伤害: <%player_level%*2>'属性中的 {var.xxx} 和 {tag.xxx} 会先替换,再计算 <...> 公式。
PlaceholderAPI 占位符
扩展标识为 lgm。PlaceholderAPI 未安装或玩家对象为空时,插件占位符返回空字符串或对应的零值。
| 占位符 | 返回内容 |
|---|---|
%lgm_tag-标签% | 当前玩家指定标签的层数。 |
%lgm_active-组ID% | 当前玩家指定映射组实际激活的映射 ID。 |
%lgm_mapped-映射ID% | 当前缓存中指定映射的第 1 条属性。 |
%lgm_mapped-映射ID:序号% | 当前缓存中指定映射的指定序号属性,序号从 1 开始。 |
%lgm_Mapped-映射ID% | mapped 前缀的大小写兼容写法。 |
%lgm_Mapped-映射ID:序号% | mapped 前缀的大小写兼容写法。 |
映射属性占位符读取最近一次计算缓存,不会因为查询而重新扫描物品或重新计算公式。映射未激活、序号无效或属性不存在时返回空字符串。
公共 API
插件提供 LyGalaxyMappedAPI 公共接口,用于向玩家添加、移除和查询临时标签。
| 方法 | 返回值 | 说明 |
|---|---|---|
addTag(Player player, String tagId, int points, long durationTicks) | boolean | 添加一个按 tick 自动过期的临时标签条目。 |
removeTag(Player player, String tagId) | boolean | 移除玩家指定标签的全部临时标签条目。 |
clearTags(Player player) | 无 | 清空玩家当前全部临时标签。 |
getTemporaryTagPoints(Player player) | Map<String, Integer> | 获取玩家当前尚未过期的临时标签层数合计。 |
API 规则:
player为空、标签 ID 为空或只有空格、points为0、durationTicks不大于0时,addTag返回false。- 标签 ID 会去除首尾空格后保存。
- 同一玩家同一标签的多次添加会独立叠加,并分别按持续 tick 数过期。
- 临时标签会与装备计算出的标签层数合并后参与映射判断。
removeTag移除不存在的标签时返回false。getTemporaryTagPoints只统计尚未过期的条目,并返回当前标签的合计层数。- 玩家退出或插件停止时,会清理该玩家的临时标签。
运行机制
- 插件按
plugin-slot异步读取物品快照,并以完整槽位配置字符串保存独立物品克隆。 - 玩家加入、关闭背包、切换快捷栏或交换主副手时,会请求刷新相关快照。
- 全局快照任务每
10tick 批量处理被标记的玩家;标签和映射计算按照thread-running-interval执行,默认间隔为20tick。 tag-check统计装备条件、玩家状态和临时标签,得到最终标签层数。mapped检查require和exclude,再按group-id选择同组最高优先级映射。- 不同组的生效映射会合并属性和药水结果。
- 属性插件写入、药水修改、消息发送和外部槽位事件在服务端主线程执行。
- 重载时先清理旧属性和由插件管理的药水,再加载新配置并重新计算在线玩家。
- 玩家退出或插件停止时,会清理属性、药水、临时标签和快照缓存。
常见问题
为什么映射没有生效?
检查以下内容:
require中的多个标签是否全部达到要求。exclude中是否有任意标签达到排斥层数。plugin-slot是否包含实际存放装备的槽位。- 外部背包插件及对应槽位 API 是否正常可用。
- 同组是否存在优先级更高且同样满足需求的映射。
mapped配置文件是否位于plugins/LyGalaxyMapped/mapped/目录,并且扩展名为.yml。papi(...)条件使用时 PlaceholderAPI 是否已安装并启用。
为什么标签层数比装备数量更多?
每条条件独立累计。命中次数会乘以该条件所在数字节点的权重,同一件物品满足多条条件时会分别计数,不会去重;临时标签也会合并到最终层数。
condition 下的数字是不是条件编号?
不是。数字代表每次条件命中增加的标签层数。例如 2 表示该条件每命中一次增加 2 层。
为什么同组的多个映射不会同时生效?
相同 group-id 的映射属于同一组。同组只保留满足需求、未触发排斥条件且优先级最高的一条;相同优先级时按映射 ID 字典序选择一条。不同 group-id 的映射可以同时生效。
为什么属性没有刷新?
确认 attribute-plugin 与已安装的属性插件名称一致,并确认对应插件已经启动。配置为 ItemLoreOrigin 时,还要确认 ItemLoreOrigin 已启动。属性插件接口不可用或配置值不支持时,属性写入不会成功。
为什么 PlaceholderAPI 条件没有命中?
确认 PlaceholderAPI 已安装并启用,并检查表达式中的占位符和比较运算符是否正确。papi(...) 支持 ==、!=、>、>=、<、<=、&& 和 ||。
为什么映射属性占位符没有返回内容?
映射属性占位符读取最近一次计算缓存。检查映射是否实际激活、属性序号是否从 1 开始,以及查询的映射 ID 是否完全一致。查询不会主动触发重新计算。
药水配置应该怎么写?
使用 TYPE:LEVEL[:SECONDS]。例如 SPEED:1 表示一级速度效果,SPEED:2:10 表示二级速度效果并指定持续 10 秒。未填写持续时间时,插件根据检测间隔生成默认持续时间。
修改配置后需要重新加载吗?
需要执行 /lgm reload。该指令仅允许 OP 执行。重载会重新读取 config.yml 和 mapped 目录中的 .yml 文件,并重新计算在线玩家状态。
tag-check 或 mapped 写在主配置中为什么没有生效?
当前版本只从 plugins/LyGalaxyMapped/mapped/ 目录中的 .yml 文件读取 tag-check 和 mapped。主 config.yml 只读取 attribute-plugin、thread-running-interval 和 plugin-slot 等运行配置。
旧版 check 或 attribute-group 配置还能使用吗?
不能。当前版本只读取 tag-check 和 mapped 节点,旧版 check、attribute-group 以及旧的冒号大括号条件格式不会被读取。
为什么使用 Origin#OffHand 后旧版本没有检测到副手?
部分旧版本没有副手 API,插件会安全返回空值。项目提供证据未确认这些版本存在可读取的副手槽位接口。