Skip to content

显示规则

LyGemSoulRing 会从玩家配置的装备槽位中读取宝石 ID,再根据 plugins/LyGemSoulRing/soulring/ 目录中的魂环配置,创建绑定到玩家实体的 DragonCore 世界贴图。

插件不会发放魂环道具。只有装备物品中的宝石 ID 与魂环配置文件的顶层 ID 完全一致时,才能生成对应魂环。

生效条件

魂环显示需要满足以下条件:

  • 服务器已安装并启用 DragonCore。插件只有检测到 DragonCore 已启用时,才会注册玩家加入、退出和按键监听器。
  • 已安装实际使用的宝石插件,并且 gem-plugin 与该宝石插件一致。
  • plugin-slot 中的槽位格式正确,且对应的装备或背包插件可用。
  • 读取到的物品不为空,并且存在物品元数据。
  • 物品中的宝石 ID 已在魂环配置文件中定义。
  • 主配置和魂环 YAML 文件能够正常读取。

插件 plugin.yml 中声明的软依赖如下:

插件用途
PlaceholderAPI处理显示和收回魂环时执行的指令变量
LyGemReload从装备物品中读取 LyGemReload 宝石 ID

DragonCore 未在 plugin.yml 中声明为依赖,但魂环贴图、按键监听和玩家状态同步都直接使用 DragonCore API。未启用 DragonCore 时,这些功能不会注册。

代码还提供 YeeGem 宝石读取,以及多个装备插件的槽位读取方式。使用这些来源时,需要服务器安装对应插件并保证版本兼容。

魂环数据来源

插件重载时会递归扫描以下目录中的全部 .yml 文件:

text
plugins/LyGemSoulRing/soulring/

子目录中的 .yml 文件也会被读取。每个文件的顶层键都会被当作一个宝石 ID,顶层键下的字段则作为对应魂环的世界贴图配置。

yaml
朱雀宝石:
  path: '魂环/h2.png'
  width: 3
  height: 3
  translateX: 0
  translateY: 2.2
  translateZ: 0
  translateEntityFront: 0
  translateEntityRight: 0
  rotateX: 90
  rotateY: 0
  rotateZ: 0
  through: false
  distance: 64
  alpha: 1
  glow: true
  followEntityDirection: false
  animationList:
    - 'ScaleAnimation'
    - 'RotateAnimation'
    - 'TranslateAnimation'

只有装备中读取到的宝石 ID 与 朱雀宝石 完全一致时,才会使用这段配置。

载入魂环时,控制台会输出对应 ID。某个顶层 ID 读取失败时,插件会输出 载入失败 和异常信息,并继续处理其他配置。

如果不同文件定义了相同的顶层 ID,后读取的数据会覆盖内存中先读取的数据。文件实际读取顺序由运行环境返回的文件顺序决定,因此不应重复定义同一个魂环 ID。

玩家运行状态

玩家加入服务器时,插件会创建一份运行数据,其中包括:

  • 当前是否已经展开魂环。
  • 当前展开状态记录的魂环 ID 列表。
  • 上一次尝试展开魂环的时间。

玩家的初始状态为隐藏。该状态只保存在运行内存中,退出服务器后会被移除,不会持久化保存。

如果 DragonCore 未启用,玩家加入监听器不会注册,玩家运行数据也不会创建。此时 /lgsr show 即使由玩家执行,也不会切换魂环状态。

展开与收回

玩家可以通过以下方式切换魂环状态:

触发方式条件行为
/lgsr show执行者是玩家,并且存在该玩家的运行数据在展开与收回状态之间切换
DragonCore 按键松开的按键与 show-soulring-key 完全一致,并且存在玩家运行数据在展开与收回状态之间切换

按键监听使用 DragonCore 的 KeyReleaseEvent,即松开按键时触发,不是按下按键时触发。

展开流程

玩家当前处于隐藏状态时,插件按以下顺序处理:

  1. 检查展开冷却。
  2. 将玩家状态设为展开,并记录本次展开时间。
  3. plugin-slot 配置的槽位中读取物品。
  4. 根据 gem-plugin 提取所有宝石 ID。
  5. 保留存在对应魂环配置的宝石 ID。
  6. 如果没有匹配结果,将状态恢复为隐藏并发送无魂环提示。
  7. 如果存在匹配结果,记录魂环 ID,执行展开指令并发送世界贴图。

展开指令只会在至少找到一个有效魂环后执行。

收回流程

玩家当前处于展开状态时,插件会:

  1. 将玩家状态改为隐藏。
  2. 清空当前记录的魂环 ID。
  3. 从所有在线玩家客户端删除该玩家编号 019 的魂环贴图。
  4. 删除当前版本带玩家 UUID 的贴图编号。
  5. 同时尝试删除旧版本不带玩家 UUID 的贴图编号。
  6. 执行 hide-soulring-command 中的指令。

收回操作不检查冷却。

插件固定清理前 20 个贴图编号。如果把 max-soulring 设置为大于 20,序号 20 及以上的贴图不会被主动收回,因此不建议将最大显示数量设置到 20 以上。

装备变更行为

玩家展开魂环后,插件不会持续监听装备变化,也不会自动重新读取宝石。

这意味着:

  • 更换装备不会自动替换已经展开的魂环。
  • 取下装备不会自动收回已经展开的魂环。
  • 修改物品中的宝石不会立即更新魂环。
  • 需要先再次触发按键或执行 /lgsr show 收回魂环,然后重新触发才能按新装备读取。

槽位读取顺序

plugin-slot 是一个字符串列表。插件会按照配置顺序逐个读取槽位:

yaml
plugin-slot:
  - 'Origin#MainHand'
  - 'Origin#Helmet'
  - 'LyInventoryReload#饰品#项链'

每个槽位最多返回一个装备物品,但一个物品可以提供多个宝石 ID。插件会把所有槽位中读取到的宝石 ID依次加入同一个列表。

以下情况会跳过当前槽位:

  • 槽位配置为 null 或空字符串。
  • 对应槽位没有物品。
  • 物品没有物品元数据。
  • 对应装备插件没有返回可用物品。

当前代码同时兼容旧版单字符串写法:当 plugin-slot 无法读取到列表内容时,会再次尝试把它作为单个字符串读取。不过仍建议使用列表格式。

槽位字符串会使用 # 分割。必须按对应类型填写足够的参数,否则可能发生数组越界、数字转换失败或插件 API 调用异常。

支持的槽位格式

类型格式读取位置
DragonCoreDragonCore#槽位名DragonCore 缓存槽位
GermPluginGermPlugin#槽位标识GermPlugin 身份槽位
LyInventoryLyInventory#背包文件#槽位LyInventory 背包中的指定槽位
LyInventoryReloadLyInventoryReload#背包ID#类型LyInventoryReload 背包中的指定槽位
YeeJewelryYeeJewelry#背包ID#槽位IDYeeJewelry 饰品背包槽位
MinecraftMinecraft#槽位ID原版玩家背包中的指定槽位
OriginOrigin#MainHand玩家主手
OriginOrigin#OffHand玩家副手
OriginOrigin#Helmet玩家头盔槽位
OriginOrigin#ChestPlate玩家胸甲槽位
OriginOrigin#Legging玩家护腿槽位
OriginOrigin#Boots玩家靴子槽位

Minecraft#槽位ID 会把槽位参数转换为整数,再调用原版背包槽位读取方法。默认配置注释约定使用 035

槽位类型不区分大小写。Origin 的槽位名称同样使用不区分大小写的比较,但建议保持表格中的标准写法。

宝石 ID 读取

gem-plugin 决定如何从每件装备中提取宝石 ID:

yaml
gem-plugin: 'LyGemReload'
配置值读取行为
LyGemReload调用 LyGemReload API,读取物品中的全部宝石 ID
YeeGem调用 YeeGem API 读取宝石数据,再从每个宝石数据中提取 gemId

配置值使用不区分大小写的比较。

如果填写其他值,插件仍会读取槽位物品,但不会从物品中提取任何宝石 ID,最终会按“没有魂环”处理。

重复宝石

当前实现不会去重宝石 ID。

同一个宝石 ID 在以下情况下可能重复进入显示列表:

  • 同一件装备包含多个相同 ID 的宝石。
  • 不同槽位装备了相同 ID 的宝石。
  • 不同物品读取出了相同 ID。

每次匹配都会作为一个独立魂环参与排序、缩放和数量限制。因此,相同的魂环配置可以被显示多次。

无匹配宝石

以下情况都会导致本次没有有效魂环:

  • 所有配置槽位都为空。
  • 读取到的物品没有宝石。
  • gem-plugin 不受支持。
  • 宝石 ID 没有在 soulring 目录中定义。
  • 对应宝石插件没有返回有效 ID。

没有有效魂环时,插件会恢复隐藏状态、清空魂环列表,并向玩家发送:

text
你没有魂环!

本次尝试仍然会更新上一次展开时间。因此,即使因为没有匹配宝石而展开失败,玩家紧接着再次尝试时也可能受到展开冷却限制。

显示数量

max-soulring 控制单个玩家发送的最大魂环数量:

yaml
max-soulring: 10

实际显示数量取决于:

  • 所有槽位中读取到的宝石总数。
  • 宝石 ID 是否存在对应魂环配置。
  • 重复宝石 ID 的数量。
  • max-soulring 的限制。

魂环按照槽位顺序和宝石插件返回的 ID 顺序排列。序号从 0 开始,并在达到 max-soulring 时停止发送。

玩家运行数据会记录全部匹配成功的魂环 ID,不会先按 max-soulring 截断;发送贴图以及向新加入玩家同步时才应用数量限制。

贴图编号

每个魂环使用以下格式生成客户端贴图编号:

text
插件名_玩家UUID_魂环序号

玩家 UUID 会区分不同玩家,魂环序号会区分同一玩家的不同魂环,避免广播贴图时互相覆盖。

收回或退出时,插件还会清理旧版格式:

text
插件名_魂环序号

旧版编号不含玩家 UUID,只用于兼容清理旧版本可能残留的贴图。

多层魂环尺寸

soulring-scale 控制后续魂环相对于自身基础尺寸的递增量:

yaml
soulring-scale: 4

计算方式如下:

text
实际宽度 = 配置宽度 + 魂环序号 × soulring-scale
实际高度 = 配置高度 + 魂环序号 × soulring-scale

假设魂环配置中的 widthheight 都是 3soulring-scale4

魂环顺序序号实际宽度实际高度
第一个033
第二个177
第三个21111

尺寸是在每个魂环自身配置的 widthheight 基础上计算,不要求不同魂环使用相同基础尺寸。

显示延迟的实际行为

show-soulring-delay 会作为 Bukkit 定时任务的周期参数:

yaml
show-soulring-delay: 5

单位为服务器 tick。

当前版本在创建定时任务之前,已经通过普通循环立即向所有在线玩家发送了一遍全部有效魂环。随后定时任务又会从第一个魂环开始,按照 show-soulring-delay 重复发送相同编号的贴图。

由于重复发送时使用相同贴图编号,后一次数据通常会覆盖前一次数据。按照当前代码,show-soulring-delay 不能实现“魂环从无到有逐圈出现”的效果,只会在首次全部显示后再次分批刷新相同贴图。

定时任务会在以下任一条件满足时停止:

  • 已处理全部匹配魂环。
  • 当前序号达到 max-soulring
  • 玩家对象为空。
  • 玩家已经离线。

任务启动延迟固定为 0 tick,执行周期使用 show-soulring-delay。该配置应填写能够作为 Bukkit 调度周期使用的正整数。

冷却机制

show-soulring-cooldown 控制从隐藏状态尝试展开魂环的冷却时间,单位为毫秒:

yaml
show-soulring-cooldown: 10000

冷却只在玩家当前处于隐藏状态、准备展开魂环时检查。收回魂环不受冷却限制。

当剩余冷却时间大于零时,插件不会:

  • 重新读取装备槽位。
  • 重新读取宝石 ID。
  • 执行展开指令。
  • 创建或发送魂环贴图。

提示由 show-soulring-cooldown-message 控制:

yaml
show-soulring-cooldown-message: '&c魂环绽放冷却中,还需{time}秒!'

{time} 会替换为剩余秒数,并保留一位小数。

该消息通过 Bukkit 的 sendMessage 直接发送,代码没有把 & 颜色符号转换为 §。因此配置中的 &c 是否能显示为颜色取决于服务器其他处理;仅按当前插件代码,它不会主动转换颜色代码。

显示与收回指令

成功匹配到魂环后,插件会执行 show-soulring-command

yaml
show-soulring-command:
  - '[console]tell %player_name% 你释放了魂环'

主动收回魂环时,插件会执行 hide-soulring-command

yaml
hide-soulring-command:
  - '[console]tell %player_name% 你收回了魂环'

每个列表元素代表一条完整指令。执行前会调用 PlaceholderAPI 处理玩家变量。

标记执行身份处理方式
[console]控制台删除标记后由控制台执行
[op]玩家临时 OP删除标记后以玩家身份执行,结束后恢复原 OP 状态
无标记玩家直接以玩家身份执行

标记检测使用字符串包含判断,并不是只检查指令开头。建议仍将标记放在指令最前方。

如果同一条指令同时包含 [op][console],代码会优先进入 [op] 分支,不会再按控制台指令处理。

展开指令在发送魂环贴图之前执行。收回指令在删除魂环贴图之后执行。

PlaceholderAPI 在代码中被直接调用。若配置了显示或收回指令,应安装并启用 PlaceholderAPI。

按键设置

show-soulring-key 设置切换魂环状态的 DragonCore 按键:

yaml
show-soulring-key: 'Z'

插件每次重载时都会调用 DragonCore API 注册该键位,并在控制台输出注册成功或失败信息。

玩家松开按键后,插件会把事件中的键名与配置值进行区分大小写的完全比较:

text
事件键名.equals(配置键名)

因此建议按 DragonCore 实际返回的标准大写键名填写,例如 Z

配置为空或键名无法注册时,可以改用 /lgsr show 切换状态。

世界贴图创建

每个有效魂环都会创建一个新的 DragonCore WorldTexture,并绑定到展开魂环的玩家 UUID:

text
WorldTexture.entity = 玩家UUID

随后插件根据魂环配置应用字段,再按照魂环序号修改 widthheight

贴图会发送给当前所有在线玩家,因此其他玩家也能看到展开者的魂环。贴图不是只发送给展开魂环的玩家本人。

世界贴图字段映射

animationList 外,魂环配置键会按照字段名反射查找 DragonCore WorldTexture 中的同名声明字段。

映射规则如下:

  • 字段名称必须完全一致,包括大小写。
  • 只查找 WorldTexture 类自身声明的字段。
  • 不存在的字段会被忽略。
  • 无法转换为目标字段类型的值会被忽略。
  • 字段赋值失败时会跳过该字段。

当前转换逻辑支持以下目标类型:

类型转换方式
int / Integer转换为整数
long / Long转换为长整数
float / Float转换为浮点数
double / Double转换为双精度浮点数
boolean / Boolean转换为布尔值
UUID按 UUID 字符串解析
String使用文本值

示例配置中已确认使用的世界贴图属性如下:

配置键值类型作用
path字符串魂环贴图路径
width数值基础宽度
height数值基础高度
translateX数值X 轴坐标偏移
translateY数值Y 轴坐标偏移
translateZ数值Z 轴坐标偏移
translateEntityFront数值相对实体前后方向的偏移
translateEntityRight数值相对实体左右方向的偏移
rotateX数值X 轴旋转角度
rotateY数值Y 轴旋转角度
rotateZ数值Z 轴旋转角度
through布尔值是否穿透地形
distance数值贴图显示距离
alpha数值贴图透明度
glow布尔值是否发光
followEntityDirection布尔值是否跟随玩家视角方向旋转
animationList字符串列表应用到贴图的动画列表

简化的魂环配置可以只填写需要覆盖的字段:

yaml
白虎宝石:
  path: '魂环/h3.png'
  width: 3
  height: 3
  translateY: 2.2
  rotateX: 90
  rotateY: 0
  rotateZ: 0
  animationList:
    - 'ScaleAnimation'
    - 'RotateAnimation'
    - 'TranslateAnimation'

没有填写的属性会保留 DragonCore WorldTexture 创建后的默认值。

动画选择

魂环通过 animationList 选择动画:

yaml
animationList:
  - 'ScaleAnimation'
  - 'RotateAnimation'
  - 'TranslateAnimation'

支持的名称如下:

名称动画类型固定方向
ScaleAnimation缩放动画无方向参数
RotateAnimation旋转动画z
TranslateAnimation位移动画z

动画名称使用不区分大小写的比较。无法识别的动画名称会被忽略,不会加入世界贴图的动画列表。

多个魂环会复用重载时创建的同一组动画配置对象。动画参数统一从主配置读取,不能在单个魂环文件中分别设置不同参数。

旋转动画

yaml
RotateAnimation:
  delay: 1000
  angle: 360.0
  duration: 3000
  cycleCount: 1
  fixed: true
  resetTime: 1
配置键类型代码默认值作用
delay整数0动画延迟
angle数值360旋转角度
duration整数6000动画持续时间
cycleCount整数1循环次数
fixed布尔值true是否固定动画效果
resetTime整数1动画重置参数

旋转方向由插件固定为 z,没有对应的方向配置键。

位移动画

yaml
TranslateAnimation:
  delay: 0
  distance: 2
  duration: 1000
  cycleCount: 1
  fixed: true
配置键类型代码默认值作用
delay整数0动画延迟
distance数值1.1位移距离
duration整数3000动画持续时间
cycleCount整数1循环次数
fixed布尔值true是否固定动画效果

位移方向由插件固定为 z。默认配置将该动画描述为上下动画,实际方向值由代码设置为 z

缩放动画

yaml
ScaleAnimation:
  delay: 0
  cycleCount: 1
  fixed: false
  fromScale: 10.0
  toScale: 1.0
  duration: 1000
配置键类型代码默认值作用
delay整数0动画延迟
cycleCount整数1循环次数
fixed布尔值false是否固定动画效果
fromScale数值3.0初始缩放值
toScale数值1.0目标缩放值
duration整数3000动画持续时间

表格中的代码默认值只会在对应配置键缺失时使用。插件自带 config.yml 已为这些字段提供另一组默认配置文件值。

多人可见与加入同步

玩家展开魂环时,每个世界贴图都会发送给当时所有在线玩家。

新玩家加入服务器后,插件会遍历内存中的玩家运行数据,把其他玩家当前处于展开状态的魂环发送给新玩家。同步时会:

  • 重新根据魂环 ID 查找当前内存中的魂环配置。
  • 重新创建世界贴图。
  • 保持原有魂环序号和尺寸递增效果。
  • 应用当前 max-soulring 数量限制。
  • 只发送给刚加入的玩家。

如果记录中的某个魂环 ID 在当前内存配置中已经不存在,该魂环会被跳过。

退出清理

玩家退出服务器时,插件会:

  1. 从运行数据表中移除该玩家。
  2. 向仍在线的所有玩家发送贴图删除请求。
  3. 清理该玩家编号 019 的当前版和旧版贴图编号。

玩家下次加入时会重新创建隐藏状态的数据,不会自动恢复退出前展开的魂环。

重载行为

执行 /lgsr reload 后,插件会:

  1. 确保默认 config.yml 存在。
  2. 重新读取主配置。
  3. 确保默认的 soulring/示例魂环.yml 存在,但不会覆盖已有文件。
  4. 重新创建三种动画数据。
  5. 清空内存中的魂环配置。
  6. 递归扫描并重新载入全部魂环 YAML。
  7. 重新注册 show-soulring-key 配置的 DragonCore 按键。

重载不会清空玩家运行数据,也不会主动删除或重建已经发送到客户端的魂环贴图。

因此,玩家已经展开的贴图不会立刻应用新配置。需要玩家先收回,再重新展开。新加入玩家的同步贴图会根据重载后的魂环配置重新创建。

指令与权限行为

插件只注册一个根指令:

text
/lgsr

plugin.yml 没有声明独立权限节点。权限由代码直接判断执行者是否为 OP 或玩家。

指令执行条件作用
/lgsr执行者是 OP显示插件帮助
/lgsr reload执行者是 OP重载主配置、动画、魂环文件和按键
/lgsr show执行者是玩家,且玩家运行数据已经建立展开或收回自己的魂环

/lgsr show 不要求玩家是 OP。控制台不能使用该子指令,因为代码只处理玩家执行者。

没有满足条件时,指令不会发送无权限提示或用法提示。

Tab 补全只会向 OP 提供 reload。虽然 /lgsr show 可以由普通玩家执行,但当前补全器不会向普通玩家或 OP 提供 show 补全。

相关配置文件

文件作用
plugins/LyGemSoulRing/config.yml宝石来源、装备槽位、按键、冷却、执行指令、显示数量、尺寸递增、显示周期和动画参数
plugins/LyGemSoulRing/soulring/*.yml宝石 ID 对应的魂环贴图字段和动画列表

修改这些文件后,使用以下指令重新载入:

text
/lgsr reload

重载指令必须由 OP 执行。