Skip to content

Title 称号

付费模块

Title 为付费模块,需要有效授权码激活。

功能定位

分组称号系统:有效期/永久、属性加成、聊天/TAB 前缀、ArcartX UI 菜单、PAPI 全量输出。

核心特性

  • 分组管理:称号按组归类(如冒险类、探索类、活动类),每组有独立显示名和排序
  • 品质系统:普通、传说、神话等多品质等级,每个品质有独立排序
  • 双类型称号text(文字称号)和 icon(图标称号),图标称号支持 ArcartX 自定义文字图标
  • 有效期 / 永久:通过 /axs title give 命令指定时长(如 7d30mpermanent),后台自动过期清理
  • 日期区间:支持 yyyy-MM-dd~yyyy-MM-dd 格式指定称号的激活日期和过期日期,区间外的称号不生效
  • 套装系统:多个称号组成一套,达到阈值后激发额外套装属性加成,UI 内实时展示进度
  • 头顶显示:称号可配置 overhead-modetexture 贴图 / text 文本),装备后自动显示在玩家头顶
  • 聊天 / Tab 前后缀:每个称号可独立配置 chat-prefixchat-suffixtab-prefixtab-suffix,通过 PAPI 接入任意聊天/Tab 系统
  • 属性加成
    • 展示属性 (display):仅在装备该称号时生效
    • 收藏属性 (collection):只要拥有且未过期即累计(收集图鉴式)
    • 两种字段形式*-attributesMap<键, 数值>)与 *-attribute-linesList<String>),详见下文《属性字段详解》
  • 四大属性插件集成:同时对接 AttributePlus、MythicLib(含基于它的 MMOItems 生态)、CraneAttribute、Symphony,各有独立开关和 source/modifier 前缀
  • UI 菜单:ArcartX UI 驱动的称号管理界面,玩家可浏览、装备、卸下、隐藏称号
  • PAPI 全量输出:拥有数量、装备信息、剩余时间、属性加成等全部通过 PlaceholderAPI 输出
  • 数据持久化:SQLite 或 MySQL,带连接池

依赖

类型依赖作用缺少时表现
必需ArcartX称号管理 UI、头顶显示和客户端图标文本模块无法提供可视化称号界面
可选PlaceholderAPI输出 %axstitle_*%,供聊天、TAB、计分板读取称号 UI 仍可用,PAPI 输出不可用
可选AttributePlus接收 *-attributes 转出的文本行与 *-attribute-lines,调用 addSourceAttributeAttributePlus 属性不生效
可选CraneAttribute同 AttributePlus。使用 addStaticAttributeSource / addAttributeSourceCraneAttribute 属性不生效
可选MythicLib只读 *-attributes(Map),键当 stat-id 注册 FLAT StatModifier;MMOItems 可通过其注册的 stat-id 间接使用本通道MythicLib stat 加成不生效
可选Symphony接收 *-attributes*-attribute-lines,按 Symphony 属性系统格式下发Symphony 属性不生效
可选MySQL 服务跨服共享称号数据默认 SQLite 可用;多服共享建议改 MySQL

启用步骤

yaml
modules:
  title:
    enabled: true

命令

管理命令(权限:arcartxsuite.admin

命令说明
/axs title status查看称号模块、数据库和缓存状态
/axs title reload重载称号配置、UI 和玩家状态
/axs title give <玩家> <称号ID> <时长>向玩家发放称号。时长如 permanent(永久)、7d12h30m2025-01-01~2025-12-31
/axs title revoke <玩家> <称号ID>收回玩家的指定称号
/axs title open <玩家>为在线玩家打开称号管理界面

玩家命令(权限:arcartxsuite.title.use

命令说明
/title/title open打开称号管理菜单
/title equip <称号ID>装备指定称号,前缀/后缀/属性立即生效
/title unequip <组ID|all>卸下某个组的已装备称号,all 卸下全部
/title hide <称号ID>隐藏指定称号(不在菜单显示但仍拥有)
/title unhide <称号ID>取消隐藏

时长格式详解

/axs title give<时长> 参数支持以下格式:

格式示例说明
permanentpermanent永久称号,无过期时间
<数字>s30s30 秒后过期
<数字>m30m30 分钟后过期
<数字>h12h12 小时后过期
<数字>d7d7 天后过期
yyyy-MM-dd~yyyy-MM-dd2025-01-01~2025-12-31日期区间,每天 0 点(系统时区)生效/失效

注意:日期区间的结束日期采用"当日结束"语义,即 2025-12-31 会持续到该日 23:59:59,而非 0 点整立即失效。

跨模块能力(Capability)

Title 模块在启动时向 ModuleContext 注册以下能力接口,供 EventPacket 等模块调用:

TitleGrantable

由 Title 模块注册,供 EventPacket 等模块授予称号。

java
boolean giveTitle(UUID playerId, String titleId, String duration, String source);
  • duration 支持 permanent7d30m2025-01-01~2025-12-31 等格式
  • source 用于日志追踪(如 "EventPacket"
  • 返回 true 表示授予成功

使用场景:EventPacket 规则引擎在触发特定事件时自动发放称号奖励。

TitleConfigQueryable

由 Title 模块注册,供外部模块查询称号配置元数据(避免直接依赖 Title 内部配置类)。

java
TitleInfo queryTitle(String titleId);
record TitleInfo(String displayName, String qualityName, String description) {}

使用场景:QuestGPS 等模块在任务奖励提示中查询称号的显示名称和品质。

PlayerDataPurgeable

由 Title 模块注册,支持 /axs purge 统一清理玩家数据。

java
String moduleId();           // 返回 "title"
int purgePlayerData(UUID);   // 删除指定玩家数据,返回影响行数
int purgeAllPlayerData();    // 清空全部玩家数据,返回影响行数

DatabaseMigratable

由 Title 模块注册,支持 /axs migrate title sqlite-to-mysql [overwrite] 跨源数据库迁移。

java
String moduleId();
MigrationResult migrateDatabase(StorageDescriptor target, boolean overwrite);
StorageDescriptor currentDescriptor();

PAPI

前缀:%axstitle_*%

统计

占位符说明
%axstitle_owned_count%拥有的称号总数
%axstitle_hidden_count%已隐藏的称号数

聊天 / Tab 前后缀

占位符说明
%axstitle_chat_<组ID>_prefix%该组已装备称号的聊天前缀
%axstitle_chat_<组ID>_suffix%该组已装备称号的聊天后缀
%axstitle_tab_<组ID>_prefix%该组已装备称号的 Tab 前缀
%axstitle_tab_<组ID>_suffix%该组已装备称号的 Tab 后缀

装备状态

占位符说明
%axstitle_equipped_<组ID>_id%该组已装备称号的 ID
%axstitle_equipped_<组ID>_name%该组已装备称号的显示名称
%axstitle_equipped_<组ID>_group%该组已装备称号所属组的显示名
%axstitle_equipped_<组ID>_quality%该组已装备称号的品质名

总展示称号

display-title.groups 配置的分组顺序,拼接已装备称号的对应字段。多组用 separator 分隔,无装备时返回 empty-text

占位符说明
%axstitle_display%总展示称号名称(拼接各组 displayName
%axstitle_display_name%%axstitle_display%
%axstitle_display_chat_prefix%总展示称号的聊天前缀拼接
%axstitle_display_chat_suffix%总展示称号的聊天后缀拼接
%axstitle_display_tab_prefix%总展示称号的 Tab 前缀拼接
%axstitle_display_tab_suffix%总展示称号的 Tab 后缀拼接

只想展示单个组的称号时,display-title.groups 只填一个组 ID;想展示多组则填多个,留空则按定义顺序展示所有组。

称号查询

占位符说明
%axstitle_owned_<称号ID>%是否拥有指定称号(true/false
%axstitle_hidden_<称号ID>%是否隐藏了指定称号
%axstitle_remaining_<称号ID>%剩余有效时间(毫秒),永久返回 永久

属性加成

占位符说明
%axstitle_display_attr_<属性键>%当前展示中称号的属性加成值
%axstitle_collection_attr_<属性键>%收藏图鉴属性加成
%axstitle_total_attr_<属性键>%展示 + 收藏 + 套装的总属性加成
%axstitle_set_bonus_attr_<属性键>%套装加成属性值

日期区间

占位符说明
%axstitle_activates_<称号ID>%称号的激活时间戳
%axstitle_effective_<称号ID>%称号当前是否在有效区间内(true/false

套装

占位符说明
%axstitle_set_<套装ID>_completion%该套装已拥有的称号数量
%axstitle_set_<套装ID>_active%该套装是否已激活(true/false

头顶显示

称号可配置装备后在玩家头顶显示称号名或贴图。有两种模式可选:

配置字段

在称号定义 YAML 中(data/title/titles/*.yml)添加以下字段:

字段类型默认值说明
overhead-modeStringnonetexture(ArcartX 贴图) / text(Scoreboard Team) / none(不显示)
overhead-textureStringTEXTURE 模式的渲染内容,使用 ArcartX 文字贴图格式(如 §k!%000001&lt;icon&gt;
overhead-widthint64TEXTURE 模式贴图宽度
overhead-heightint64TEXTURE 模式贴图高度
overhead-offset-ydouble2.3TEXTURE 模式 Y 轴偏移(越大越高)
overhead-prefixStringTEXT 模式的玩家名前缀
overhead-suffixStringTEXT 模式的玩家名后缀

模式一:TEXTURE(推荐)

使用 ArcartX 客户端渲染引擎(WorldTextureEffect),文字以自定义字体贴图形式显示在玩家头顶,效果同 UI 中的 Text 控件。需要服务器安装 ArcartX 插件。

yaml
starwalker:
  enabled: true
  group: exploration
  display-name: "&6星轨行者"
  overhead-mode: texture
  overhead-texture: "§k!%000001<icon>"
  overhead-width: 80
  overhead-height: 20
  overhead-offset-y: 2.3
  • overhead-texture 使用 ArcartX 文字贴图格式 §k!%000001&lt;icon&gt;,与 UI 和聊天中使用的格式一致
  • 贴图始终面向观察者(billboard 模式)
  • ArcartX 未安装时自动降级为 TEXT 模式

模式二:TEXT

纯服务端实现,通过 Scoreboard Team 的 prefix/suffix 在玩家名称旁显示文字。无需任何额外插件。

yaml
adventurer:
  enabled: true
  group: adventure
  display-name: "&0冒险者"
  overhead-mode: text
  overhead-prefix: "&7[冒险者] "
  overhead-suffix: ""
  • 受 Minecraft 原版限制,前缀/后缀长度有限
  • 其他 Scoreboard 相关插件可能冲突(如已有 Team 管理)

降级行为

条件实际行为
overhead-mode: texture 且 ArcartX 正常使用 ArcartX WorldTextureEffect 渲染
overhead-mode: texture 但 ArcartX 不可用自动降级到 TEXT 模式(需配好 prefix/suffix)
overhead-mode: text使用 Scoreboard Team
overhead-mode: none 或未配置不显示头顶称号

触发时机

  • 玩家登录后加载称号状态时
  • 装备 / 卸下称号时
  • 称号过期被清理时

系统遍历玩家已装备的所有分组称号,选取第一个 overhead-mode != none 的称号进行头顶显示。同一时间只能显示一个头顶称号。

属性字段详解

每个称号可以同时使用两类字段,两类可共存、互不覆盖:

称号目录位于 data/title/titles/*.yml,建议按称号组分文件:

yaml
# data/title/titles/adventure.yml
newcomer:
  enabled: true
  group: adventure
  quality: common
  display-name: "&e初来乍到"
  # 佩戴生效
  display-attributes:           # Map<键, 数值>
    attack: 1
    max_health: 10
  display-attribute-lines:      # List<String>
    - "暴击率:5(%)"
    - "生命力:100"

explorer:
  enabled: true
  group: adventure
  quality: legend
  display-name: "&6探险者"
  # 拥有即累计(未装备也算)
  collection-attributes:
    knowledge: 1
  collection-attribute-lines:
    - "魔力上限:50"

主配置 ArcartXTitle.yml 中的称号目录键:

yaml
# 称号定义目录,相对模块数据目录。
# 建议按称号组分文件,例如 titles/adventure.yml、titles/exploration.yml。
titles-directory: "titles"

下发矩阵

字段类型AttributePlusCraneAttributeMythicLibMMOItems原版 Bukkit Attribute
*-attributesMap<键, 数值>✅ 转成 键:数值 行下发✅ 同 AP✅ 键作为 stat-id 注册 FLAT modifier⚠️ 仅当键是 MMOItems 在 MythicLib 中注册的 stat-id 时生效❌ 不接入
*-attribute-linesList<String>✅ 原样下发给 addSourceAttribute✅ 同 AP❌ 完全忽略

选型准则

场景选择示例
纯数值增量,且要让 MythicLib 生效*-attributesattack: 1max_health: 10
需要百分比 / 中文属性名 / AP 自定义语法*-attribute-lines"暴击率:5(%)""生命力:100"
同一属性要同时走 MythicLib 和 AP两者并写Map 里写英文 stat-id,lines 里写中文原生行

各插件的实际行为

AttributePlus / CraneAttribute

以 source 名称下发一批字符串行,由插件自己解析语法:

  • display-attributes 的每个项 → 转成“键:数值”字符串
  • display-attribute-lines 的每个项 → 原样使用
  • 两者合并后调用 addSourceAttribute(attrData, "AXS_TITLE_DISPLAY", lines, false)(AP)或 addStaticAttributeSource(attrData, "AXS_TITLE_DISPLAY", lines)(CA)
  • collection 同理,但使用 source 名 AXS_TITLE_COLLECTION
  • source 名前缀可在 ArcartXTitle.ymlattributeplus.source-prefix / craneattribute.source-prefix 中调整

因此任何 AttributePlus / CraneAttribute 支持的属性名(含中文、百分比、区间、自定义属性)都可以直接在 lines 里写。

MythicLib

严格只读 *-attributes (Map),*-attribute-lines 被完全忽略

  • 每个键经 MythicLibStatKeyNormalizer.normalize(key) 规范化后查 statManager.isRegistered(statId),未注册的 stat-id 会记志警告并跳过
  • 合格项构造为 StatModifier(name, statId, value, FLAT, OTHER, OTHER) 以 modifier 名称注册到玩家 StatMap
  • modifier 名称默认 AXS_TITLE_DISPLAY_<statId> / AXS_TITLE_COLLECTION_<statId>,可在 mythiclib.modifier-prefix 中调整
  • 装备 / 卸下 / 拥有变动时老的 modifier 会被先 remove 再重新 register,避免叠加

MMOItems

本模块 没有独立的 MMOItems 集成代码。MMOItems 本身基于 MythicLib stat 系统,只要你在 *-attributes 里写的键是 MMOItems 注册的 stat-id(如 MAX_HEALTHATTACK_DAMAGEMOVEMENT_SPEED),就会随 MythicLib 通道生效。*-attribute-lines 对 MMOItems 不生效。

Symphony

接收 *-attributes(Map)与 *-attribute-lines(List<String>),按 Symphony 属性系统格式下发:

  • display-attributes 的每个项 → 转成 Symphony 属性键值对
  • display-attribute-lines 的每个项 → 原样下发
  • 两者合并后调用 Symphony API 注册到玩家
  • collection 同理,source 名可在 ArcartXTitle.ymlsymphony.source-prefix 中调整(默认 AXS_TITLE

原版 Bukkit Attribute

本模块不直接接入 org.bukkit.attribute.Attribute。如需原版 GENERIC_MAX_HEALTH 等生效,请通过 AttributePlus / CraneAttribute / MythicLib / Symphony 的映射能力(这些插件内部都可以把自己的属性映射到原版 Attribute)间接实现。

常见问题

  • 在菜单里看到属性显示 -:检查字段名是不是拼错了。有效的只有这 4 个:display-attributescollection-attributesdisplay-attribute-linescollection-attribute-lines。其他如 display-attributeplus 之类不被识别。
  • 中文属性名不生效:确保写在 *-attribute-lines 里(不是 Map),且 AttributePlus / CraneAttribute 的属性表中存在该中文属性。
  • MythicLib 警告 stat 未注册*-attributes 里的键不是 MythicLib/MMOItems 仓库里已有的 stat-id。请查 MythicLib/stats/*.yml 或 MMOItems 属性配置。
  • 菜单里同名属性堆在一行 / 分散显示:本版本起,后端会把同名同类(名:数值 形式)的行累加合并为一项,并把 *_attributes_text 字段以 List&lt;String&gt; 形式发送,UI Text 控件的 texts 字段拿到 List 会自动按行渲染。若仍异常,请确认 plugins/ArcartXSuite/ui/title_menu.yml 已被新版本覆盖。
  • 属性行没有颜色 / 颜色不对:在 ArcartXTitle.ymlui.attribute-line-color 配置统一改(默认 &0),不要在每个称号定义里加颜色码。

服务端 → UI 数据契约(属性相关)

打开称号菜单时,packet 携带的属性字段统一为 List<String>(每行一个属性)。ArcartX Text 控件的 texts 字段拿到 List 时会自动按多行渲染,所以 UI 端只要把字段直接绑给 texts 即可:

字段(List<String>含义
selected_display_attributes_text当前选中称号的佩戴属性
selected_collection_attributes_text当前选中称号的收集属性
display_attributes_text玩家当前装备所有称号汇总后的佩戴属性
collection_attributes_text玩家所有已拥有称号汇总后的收集属性
total_attributes_text装备 + 收集 + 套装加成的总属性
set_bonus_attributes_text已激活套装提供的额外属性
display_title_name总展示称号名称(按 display-title 配置拼接)
display_title_chat_prefix总展示称号聊天前缀
display_title_chat_suffix总展示称号聊天后缀
display_title_tab_prefix总展示称号 Tab 前缀
display_title_tab_suffix总展示称号 Tab 后缀

所有字段在生成时都会做同名同类合并(解析为 名:数值名:数值% 的行会累加,其他形如 名:1~5 / 名:5(%) 的复杂行原样保留并去重),并在每一项前自动加上颜色前缀。空列表时会发出单元素列表 [<前缀><占位符>]

单行自带颜色码的处理:如果你在某条 *-attribute-lines 里写了 "&4暴击率:5(%)" 这种自带颜色码的行,模块会:

  1. 解析时剥离行首颜色码(&§ + 一字符,可多组),用剥离后的属性名作为合并键;
  2. 合并后输出时把首次出现的颜色码重新拼回去,所以 &4暴击率:5暴击率:3 会合并成 &4暴击率: 8
  3. 最后 colorize 阶段会检测行首是否已有颜色码:有就跳过默认 attribute-line-color 前缀,没有才拼上。

也就是说:单行优先级 > 全局默认。需要某条属性高亮就在那一行写颜色码即可。

颜色与占位符配置

颜色前缀和空占位符不在称号定义里写,而是在 ArcartXTitle.yml 顶部 ui: 节统一配置:

yaml
ui:
  ui-id: "AXS:title_menu"
  register-ui-on-enable: true
  # 属性列表每行的统一颜色前缀,支持 &0~&f、&l 等
  attribute-line-color: "&0"
  # 属性列表为空时的占位字符串(不需要自己加颜色前缀,模块会自动拼)
  empty-attribute-placeholder: "-"

UI 推荐用法

title_menu.yml 默认采用最简洁的"标题 Text + 列表 Text"两件套:

yaml
selected_display_label:
  type: Text
  attribute:
    width: 660
    fontSize: 49
    texts: "'&0佩戴属性'"
selected_display_value:
  type: Text
  attribute:
    width: 660
    fontSize: 49
    lineSpace: 4
    texts: var.selectedDisplayAttributesText   # 直接绑 List<String>,自动多行

如果想自己控制每行渲染(例如不同奇偶行染色、加图标等),也可以用 VStack + Observer + self.entry 迭代,写法见 set_stack / set_observer 的官方示例。

总展示称号配置

display-title 配置节控制「总展示称号」的行为——把多个组的已装备称号拼接为一个字符串,供 PAPI 和 UI 使用。

yaml
display-title:
  # 要展示的分组列表,按此顺序拼接。
  # 留空 [] 表示按分组定义顺序展示所有组。
  # 只想展示单个组的称号时,只填一个组 ID。
  groups: []

  # 多组拼接时的分隔符。
  separator: " "

  # 没有装备任何称号时返回的文本。留空则返回空字符串。
  empty-text: ""

典型场景

场景配置%axstitle_display% 输出示例
只展示冒险组称号groups: [adventure]勇者
展示冒险+探索两组groups: [adventure, exploration]勇者 探险家
展示所有组(默认)groups: []勇者 探险家 节日特赠
没装备任何称号empty-text: "无称号"无称号

完整配置示例

以下是一份可直接使用的 ArcartXTitle.yml 骨架,覆盖存储、UI、分组、品质、套装和属性插件前缀:

yaml
# 称号定义目录,相对模块数据目录(plugins/ArcartXSuite/modules/title/)
titles-directory: "titles"

settings:
  debug: false
  # 过期清理周期(ticks),默认 1200 = 60 秒
  expiration-cleanup-interval-ticks: 1200

storage:
  mode: sqlite          # sqlite 或 mysql
  pool-size: 4
  sqlite:
    file: "titles.db"
  mysql:
    host: "127.0.0.1"
    port: 3306
    database: "arcartxsuite"
    username: "root"
    password: ""

ui:
  ui-id: "AXS:title_menu"
  register-ui-on-enable: true
  attribute-line-color: "&0"
  empty-attribute-placeholder: "-"

display-title:
  groups: []
  separator: " "
  empty-text: ""

# 分组定义(用户可自由增删)
groups:
  adventure:
    name: "冒险"
    sort-order: 0
  exploration:
    name: "探索"
    sort-order: 1

# 品质定义(用户可自由增删)
qualities:
  common:
    name: "普通"
    sort-order: 0
  legend:
    name: "传说"
    sort-order: 1

# 套装定义(用户可自由增删)
sets:
  starwalker_set:
    display-name: "星轨套装"
    required-titles:
      - starwalker
      - stargazer
    completion-threshold: 2
    bonus-attributes:
      luck: 5
    bonus-attribute-lines:
      - "星轨之力:10"

# 属性插件 source/modifier 前缀
attributeplus:
  source-prefix: "AXS_TITLE"
mythiclib:
  source-prefix: "AXS_TITLE"
craneattribute:
  source-prefix: "AXS_TITLE"
symphony:
  source-prefix: "AXS_TITLE"

提示groupsqualitiestitlessets 均为动态节点,用户增删不会被 ConfigDiagnosticEngine 判定为废弃。

基于 GPL-3.0 许可发布