# ArcartX Documentation (Full)
> ArcartX 是一个 Minecraft 服务端插件框架,提供自定义模型、UI系统、特效、脚本引擎等功能。
## AI 助手
URL: https://wiki.arcartx.com/docs/ai_assistant
本文档站集成了 AI 问答助手,你可以用自然语言向它提问关于 ArcartX 的任何问题,AI 将基于文档内容为你作答。
AI 助手采用 BYOK(Bring Your Own Key)模式,所有请求均从你的浏览器直接发送至你配置的 API 服务,本站不经手任何请求,也不存储你的密钥。
## 使用方式
点击页面右下角的聊天气泡按钮即可打开 AI 助手面板。首次使用需要配置 API 连接信息。
### 配置 API
打开面板后,点击右上角的齿轮图标进入设置。填写以下信息:
- **Base URL**:你的 API 服务地址,例如 `https://ark.cn-beijing.volces.com/api/v3`
- **API Key**:你的 API 密钥
- **模型**:点击「获取模型列表」自动加载可用模型,或直接手动输入模型名称
### 开始提问
配置保存后,在输入框中输入你的问题,按回车或点击发送即可。AI 会基于本站文档内容进行回答,支持流式输出。
## 支持的 API 服务
AI 助手兼容所有 OpenAI API 格式的服务,包括但不限于:
- [火山引擎(豆包)](https://www.volcengine.com/docs/82379/1099455)
- [DeepSeek](https://platform.deepseek.com/)
- [OpenAI](https://platform.openai.com/)
- [硅基流动](https://siliconflow.cn/)
- 以及其他兼容 OpenAI 格式的第三方服务
部分 API 服务可能存在浏览器跨域(CORS)限制,导致无法从前端直接请求。如果遇到获取模型列表失败的情况,请直接手动输入模型名称,通常不影响正常对话。
## llms.txt 协议
本站还提供了 [llms.txt 协议](https://llmstxt.org/) 支持,方便外部 AI 工具(如 Cursor、ChatGPT 等)抓取和理解文档内容:
- [`/llms.txt`](/llms.txt) — 精简版,包含所有页面的标题与链接索引
- [`/llms-full.txt`](/llms-full.txt) — 完整版,包含所有页面的完整文档内容
你可以在 AI 编程工具中将上述链接添加为文档源,让 AI 更好地理解 ArcartX 的用法。
---
## 序章
URL: https://wiki.arcartx.com/docs
## 关于 ArcartX
ArcartX 是一套面向 Minecraft 服务器的客户端渲染与交互框架,由服务端插件和客户端 MOD 两部分组成。它为服务器开发者提供了UI 界面、自定义模型、粒子特效、相机控制、键位绑定等一系列能力,让你无需编写客户端 MOD 就能实现丰富的视觉和交互效果。
关于名字:ArcartX 源自 "Arc" 与 "Art" 的结合,你也可以简称为 "AX"。
QQ 交流群:832063293
## 支持的版本
### 客户端 MOD
| Minecraft 版本 | Forge | NeoForge | Fabric |
|:------------:|:-----:|:--------:|:------:|
| 1.20.1 | ✅ | | ✅ |
| 1.20.4 | | | ✅ |
| 1.21 | ✅ | | |
| 1.21.1 | | ✅ | ✅ |
| 1.21.4 | | | ✅ |
| 1.21.8 | | | 即将支持 |
| 1.21.11 | | | 即将支持 |
### 服务端插件
支持 Spigot / Paper 及其分支,兼容以下 Minecraft 版本:
1.18.1、1.18.2、1.19、1.19.1、1.19.2、1.19.3、1.19.4、1.20.1、1.20.2、1.20.4、1.21.1、1.21.3、1.21.4
## 第三方插件兼容
ArcartX 插件端会自动检测以下第三方插件,在它们存在时启用对应的兼容功能:
### 技能与实体
| 插件 | 兼容内容 |
|:------------|:------------------------------------------------------------------------------|
| MythicMobs | 提供自定义技能词条(模型、动画、碰撞箱、隐藏骨骼、默认状态、3D 音效、基岩粒子、锤地特效、UI 通讯、代理碰撞箱、镜头摇晃、坐骑系统等),支持模型投掷物 |
| ModelEngine | 可共存其碰撞箱 |
| Adyeshach | 虚拟实体的模型和尺寸数据同步 |
### 属性提供者
| 插件 | 兼容内容 |
|:---------------|:------------------|
| AttributePlus | 属性读取与写入(兼容新旧两个版本) |
| AstraXHero | 属性读取与写入 |
| CraneAttribute | 属性读取与写入 |
### 经济与物品提供者
| 插件 | 兼容内容 |
|:-------------|:-------|
| Vault | 经济系统对接 |
| PlayerPoints | 点券经济对接 |
| NeigeItems | 物品生成对接 |
| MythicMobs | 物品生成对接 |
### 其它
| 插件 / MOD | 兼容内容 |
|:--------------------------|:------------------------------------|
| PlaceholderAPI | 占位符变量支持 |
| JEI | UI 中显示 JEI 侧边栏) |
| Shoulder Surfing Reloaded | 第三人称相机兼容(Forge 1.20.1,需关闭 AX 自定义相机) |
## 使用须知
启程之前,请驻足细览ArcartX 的用户协议(EULA)。使用即代表认同。若有任何不适,请暂缓脚步。
ArcartX 本是无偿之礼。若为付费获取,当知其为歧路。
流转有度,分享有方。唯允将原始之作融入你的客户端与玩家分享,任何形式的转载都将是不被允许的。
对于任何越界之举,法律将是共同的准绳。
---
## 最佳实践
URL: https://wiki.arcartx.com/docs/chronos/10_best_practice
## 概述
本章节总结了使用 Chronos 动作系统时的最佳实践,帮助你设计出流畅、平衡、有趣的战斗系统。
---
## 状态组规划
合理划分状态组,便于条件检查和状态管理。
### 推荐的状态组划分
| 状态组 | 说明 | 包含状态示例 |
|----------|-----------|--------------|
| **攻击** | 普通攻击、技能攻击 | 攻击1段、攻击2段、重击 |
| **闪避** | 闪避、翻滚 | 前闪、后闪、侧闪 |
| **格挡** | 格挡、招架 | 格挡、完美格挡 |
| **受控** | 受击、眩晕、击飞 | 受击、硬直、倒地 |
| **特殊运动** | 冲刺、跳跃攻击 | 冲刺斩、跳劈 |
### 配置示例
``` yaml
state:
攻击1段:
group: "攻击"
conditions:
blocked_group:
- "受控" # 受控时无法攻击
- "特殊运动" # 特殊运动时无法普通攻击
闪避:
group: "闪避"
conditions:
blocked_group:
- "受控" # 受控时无法闪避
受击:
group: "受控"
# 受控状态一般没有 blocked_group,因为它是被动进入的
```
**设计建议:** 状态组的划分应该反映动作的"类型",而不是具体的动作名称。这样可以更容易地添加新动作,而不需要修改现有的条件配置。
---
## 窗口时机设计
窗口的时机设计直接影响战斗的手感和节奏。
### 典型攻击状态时间线
```mermaid
gantt
title 典型攻击状态时间线 (500ms)
dateFormat X
axisFormat %L ms
section 阶段
前摇期 (不可打断) :0, 100
判定期 (攻击判定) :crit, 100, 150
持续期 :150, 300
后摇期 :300, 500
section 窗口
霸体窗口 :active, 100, 200
派生窗口 :active, 300, 450
取消窗口 :350, 500
```
### 配置示例
``` yaml
攻击1段:
duration: "500"
windows:
# 霸体保护攻击动作
super_armor:
start: 100
end: 200
# 派生窗口在后摇期
derive:
start: 300
end: 450
# 取消窗口略晚于派生窗口开始
cancel:
start: 350
end: 500
execute:
攻击判定:
at: 150
expression: "self.castMythicMobSkill('attack1_damage', 1.0)"
```
### 闪避状态时间线
```mermaid
gantt
title 典型闪避状态时间线 (400ms)
dateFormat X
axisFormat %L ms
section 阶段
起手期 :0, 50
无敌期 :active, 50, 250
恢复期 :250, 400
section 窗口
无敌帧 :crit, 50, 250
派生窗口 :active, 250, 380
取消窗口 :380, 400
```
### 配置示例
``` yaml
闪避:
duration: "400"
windows:
invincible:
start: 50
end: 250
invincible_tag_duration: 500 # 完美闪避标记
derive:
start: 250
end: 380
cancel:
start: 380
end: 400
```
**设计建议:**
- 前摇期应该足够短,让玩家感觉响应迅速
- 无敌帧不要太长,否则会降低难度
- 派生窗口应该在动作自然的衔接点
---
## 输入缓冲调优
输入缓冲参数会显著影响战斗的手感。
### 快节奏战斗
适用于:快速连击、高APM操作
``` yaml
setting:
input_buffer:
enabled: true
max_size: 3 # 允许较多预输入
lifetime: 200 # 较短的有效期,要求快速输入
```
### 稳重型战斗
适用于:策略性战斗
``` yaml
setting:
input_buffer:
enabled: true
max_size: 2 # 限制预输入数量
lifetime: 400 # 较长的有效期,容错性更高
```
**调优建议:**
- `max_size` 越大,连招越容易衔接,但也可能导致误操作
- `lifetime` 越长,预输入窗口越宽松,对新手更友好
- 注意,如果你使用了组合条件,则需要有对等数量的缓冲大小。比如你有一个组合键有三个按键条件,缓冲区大小至少为3
---
## 连招深度建议
合理的连招深度可以让战斗既有深度又不失可操作性。
### 推荐深度
| 类型 | 推荐深度 | 说明 |
|-----------|----------|---------------|
| **普通攻击链** | 3-5段 | 太短缺乏变化,太长难以记忆 |
| **技能分支** | 每段0-2个分支 | 提供选择而不造成困惑 |
| **搓招技能** | 2-4个输入序列 | 平衡难度和可执行性 |
### 普通攻击链示例
``` yaml
combo:
攻击1段:
input:
type: MOUSE_CLICK
value: LEFT
derive:
攻击2段:
input:
type: MOUSE_CLICK
value: LEFT
derive:
攻击3段:
input:
type: MOUSE_CLICK
value: LEFT
derive:
# 终结技分支
上挑:
input:
type: MOUSE_CLICK
value: RIGHT
攻击4段:
input:
type: MOUSE_CLICK
value: LEFT
# 中途分支
横扫:
input:
type: MOUSE_HOLD
value: LEFT
```
**设计建议:**
- 让玩家能够在任何时候取消到防御性动作(闪避、格挡)
- 提供明显不同的派生路线(如:快速连击 vs 重击终结)
- 终结技应该有更高的伤害或特殊效果作为奖励
---
## 性能优化
在配置复杂的动作系统时,注意以下性能优化建议:
### 表达式优化
避免在 `expression` 中使用复杂计算:
``` yaml
# ❌ 不推荐:复杂计算
conditions:
expression: "Math.sqrt(self.getPosX() * self.getPosX() + self.getPosZ() * self.getPosZ()) < 100"
# ✅ 推荐:简单判断
conditions:
expression: "self.getFood() >= 3 && !self.isFlying()"
```
### 缓冲点优化
合理设置 `buffer_at`,减少无效的预输入检查:
``` yaml
state:
攻击1段:
duration: "500"
# 在派生窗口开始时才检查预输入
buffer_at: 300 # 对应 derive.start
windows:
derive:
start: 300
end: 450
```
### 状态组优化
使用状态组进行批量条件阻止,而不是逐个列出状态:
``` yaml
# ❌ 不推荐:逐个列出
conditions:
blocked_states:
- "受击"
- "眩晕"
- "击飞"
- "倒地"
# ✅ 推荐:使用状态组
conditions:
blocked_group:
- "受控"
```
---
## 常见问题排查
### 动作无法触发
**检查清单:**
1. 确认状态已在 `state` 节点中声明
2. 确认状态已在 `combo` 节点中配置输入
3. 检查 `conditions.expression` 是否返回 `true`
4. 检查是否被 `blocked_group` 阻止
5. 检查冷却是否已结束
### 派生无法衔接
**检查清单:**
1. 确认当前时间在 `derive` 窗口内
2. 确认输入类型和值配置正确
3. 如果使用组合输入,检查 `mode` 是否正确
4. 检查派生的 `condition` 表达式
### 输入被"吞掉"
**可能原因:**
1. `input_buffer.lifetime` 设置过短
2. `input_buffer.max_size` 设置过小
3. `buffer_at` 时间点设置不合理
---
## 总结
设计一个优秀的动作系统需要平衡多个因素:
1. **响应性** - 让玩家感觉动作立即响应
2. **可读性** - 动作反馈清晰,玩家知道发生了什么
3. **深度** - 提供足够的选择和技巧空间
4. **平衡** - 风险与收益成正比
不断测试和迭代是关键。建议先从简单的配置开始,逐步添加复杂性,并持续收集玩家反馈。
---
## 说明
URL: https://wiki.arcartx.com/docs/chronos/1_start
# 说明
- ArcartX-Chronos 隶属于 ArcartX 生态系统。它是一个高级玩家动作状态控制器,用于实现类似动作游戏中的连击系统、战斗技能派生、状态机控制等功能。
- 这是一款付费插件,你需要购买后才能使用。
- 你可以在[ArcartX社区](https://arcartx.com/resources/arcartx-chronos-ke-luo-nuo-si.54/)购买。
---
## 什么是 Chronos?
Chronos 是一个专为 Minecraft + ArcartX 服务器设计的**高级动作控制器系统**。它模拟了动作游戏的战斗机制,为你的服务器带来更舒适的动作系统体验:
| 特性 | 说明 |
|--------------|-------------------|
| ⚔️ **连招系统** | 支持多段连击、分支派生 |
| 🛡️ **窗口机制** | 取消窗口、派生窗口、无敌帧、霸体 |
| 🎮 **输入缓冲** | 预输入支持,提升操作手感 |
| ⌨️ **组合输入** | 支持组合键、多种触发方式、搓招系统 |
| 🔄 **状态机** | 完整的状态生命周期管理 |
---
## 核心概念
在开始使用 Chronos 之前,你需要理解以下核心概念:
| 概念 | 说明 |
|-------------------------|-----------------------|
| **控制器 (Controller)** | 一套完整的动作配置,通常对应一种武器或角色 |
| **状态 (State)** | 一个具体的动作,如"攻击1段"、"闪避" |
| **连招链 (Combo Chain)** | 状态之间的输入派生关系 |
| **窗口 (Window)** | 状态执行过程中的特殊时间段 |
| **输入缓冲 (Input Buffer)** | 临时存储玩家输入,用于预输入 |
**理解这些概念非常重要!** 控制器就像是一把武器的"技能书",里面定义了所有可能的动作(状态),以及这些动作之间如何衔接(连招链)。
---
## 架构设计
### 分层子系统架构
Chronos 采用分层子系统设计:
```mermaid
flowchart TB
subgraph Player["Coordinator (协调器)"]
direction LR
P1["持有各子系统引用"]
P2["协调输入 → 状态 → 输出流程"]
end
Player --> InputSystem
Player --> StateRunner
Player --> TransitionEngine
Player --> ControllerSystem
subgraph InputSystem["InputSystem 输入系统"]
I1["输入缓冲"]
I2["预输入"]
end
subgraph StateRunner["StateRunner 状态运行器"]
S1["状态更新"]
S2["窗口管理"]
end
subgraph TransitionEngine["TransitionEngine 转换引擎"]
T1["输入匹配"]
T2["状态转换"]
end
subgraph ControllerSystem["Controller 控制器"]
C1["切换管理"]
C2["冷却管理"]
end
```
### 子系统职责
| 子系统 | 职责 |
|-----------------------------|-------------------------------|
| **InputSystem (输入系统)** | 管理输入缓冲队列、处理预输入存储、清理过期输入 |
| **StateRunner (状态运行器)** | 管理状态生命周期、执行状态更新、管理当前激活的窗口 |
| **TransitionEngine (转换引擎)** | 处理输入匹配、执行状态转换、处理 AUTO 自动衔接 |
| **Controller (控制器)** | 管理控制器切换、维护冷却时间、管理 Glimmer 上下文 |
---
## 功能一览
### 1. 状态控制器
- 为每个玩家配置独立的状态控制器
- 每个控制器包含多个状态 (State),如攻击、防御、闪避等
- 状态之间可以进行派生 (Derive) 和 取消 (Cancel) 转换
- 支持控制器继承,子控制器可以继承父控制器的状态配置
### 2. 连招链
- 配置复杂的连击派生路径
- 支持预输入 - 玩家可在当前动作结束前输入下一个动作
- 支持窗口期机制 - 包括派生窗口、取消窗口、霸体窗口、无敌窗口
- 配置衔接时间点来控制动作之间的衔接节奏
### 3. 输入系统
- 支持键盘按键(可自定义绑定)
- 支持鼠标操作 - 区分点击 (Click) 和长按 (Hold)
- **OR 模式** - 多种触发方式任选其一
- **AND 模式** - 组合键同时按下
- **SEQUENCE 模式** - 搓招系统,按顺序输入
### 4. Glimmer 脚本
- 集成了 Glimmer 脚本系统,深度定制每一步的效果
### 5. 高级机制
- 每个状态可配置进入条件
- 支持冷却时间 (Cooldown) 控制
- 支持蓄力机制 (Charge)
- 支持无敌窗口格挡成功通过条件派生完美闪避反击/处决
---
## 状态生命周期
理解状态的生命周期对于正确配置动作至关重要:
```mermaid
flowchart LR
A["条件检查"] --> B["进入状态"]
B --> C["执行中"]
C --> D["状态结束"]
C --> E["窗口激活判定"]
C --> F["执行点触发"]
```
- **条件检查**: 检查玩家是否满足进入状态的条件(表达式、冷却、被阻止的状态组等)
- **进入状态**: 初始化状态,发送客户端动画同步
- **执行中**: 每Tick检查窗口激活、触发执行点
- **状态结束**: 清理状态,处理自动衔接
---
## 输入缓冲机制
输入缓冲是提升操作手感的关键机制,让玩家的操作更加流畅:
```mermaid
sequenceDiagram
participant P as 玩家
participant B as 输入缓冲
participant S as 状态机
Note over S: 状态执行中...
P->>B: 输入下一个动作
B->>B: 存储输入
Note over S: 进入派生窗口
B->>S: 释放缓冲的输入
S->>S: 状态转换
Note over S: 下一状态开始
```
**什么是输入缓冲?** 玩家可以在当前动作还没结束时就输入下一个动作,这个输入会被暂时存储起来,等到进入派生窗口时自动执行。这就像格斗游戏中的"预输入"机制,让连招更加顺畅。
---
## 前后端状态机
**重要概念:前后端状态机的配合**
- **服务端状态机**: Chronos 提供的状态机,负责处理输入、条件判断、状态转换逻辑
- **客户端状态机**: ArcartX 提供的状态机,负责播放动画、处理视觉效果、原版动作播放
你需要结合前后端状态机,才能实现完整的功能:
1. 服务端状态 `stateName: "attack1"` 对应客户端控制器中的状态
2. 当服务端进入某个状态时,会通知客户端播放对应的动画
3. 服务端的 `duration` 应与客户端动画时长匹配
---
## 快速开始
### 创建控制器配置文件
在 `plugins/ArcartX_Chronos/controllers/` 目录下创建配置文件:
```yaml
# my_weapon.yml
setting:
client_controller_id: "my_weapon"
input_buffer:
enabled: true
max_size: 3
lifetime: 300
state:
攻击1段:
controller: "main"
stateName: "attack1"
speed: "1"
duration: "500"
group: "攻击"
windows:
derive:
start: 300
end: 450
combo:
攻击1段:
input:
type: MOUSE_CLICK
value: LEFT
```
### 为玩家设置控制器
通过命令:
- /chronos set 玩家 控制器ID
### 测试
玩家点击鼠标左键,即可触发 "攻击1段" 状态!
---
> **官方QQ交流群:832063293**
---
## 如何安装
URL: https://wiki.arcartx.com/docs/chronos/2_setup
## 安装须知
**Chronos 的安装特点:** 与 ArcartX 的混合型架构不同,Chronos 只需要在**服务端**安装插件即可,无需客户端额外配置。
---
## 前后端状态机概念
在开始安装之前,请先理解以下概念:
```mermaid
flowchart LR
subgraph Server["服务端"]
S["Chronos 状态机"]
end
subgraph Client["客户端"]
C["ArcartX 状态机"]
end
S <-->|"状态同步"| C
```
| 状态机类型 | 提供者 | 职责 |
|------------|---------|--------------------|
| **服务端状态机** | Chronos | 处理输入、条件判断、状态转换逻辑 |
| **客户端状态机** | ArcartX | 播放动画、处理视觉效果、原版状态播放 |
你需要结合前后端状态机,才能实现完整的动作系统功能。
---
## 前置要求
在安装 Chronos 之前,请确保满足以下条件:
| 要求 | 说明 |
|-------------------|--------------------------------------------|
| **ArcartX** | 必须前置,需要先安装 ArcartX 插件 |
| **Minecraft 服务端** | 支持 Spigot/Paper 及其分支 |
| **授权码** | 在 [ArcartX 社区](https://arcartx.com/) 购买后获取 |
---
## 安装流程
### 获取插件文件
购买插件后,在 **许可证** 页面可以:
- 下载 `ArcartX_Chronos_Plugin-<版本号>.jar` 文件
- [查询你的授权码 ID 和 KEY](https://arcartx.com/resources/market-place-user/licenses)
请通过官方渠道下载插件,避免使用来源不明的文件。
### 上传并生成配置
1. 将 `ArcartX_Chronos_Plugin-<版本号>.jar` 放入服务端的 `plugins` 目录
2. 重启服务器
3. 插件会自动生成 `ArcartX_Chronos` 配置文件夹
如果 `plugins` 目录内没有出现 `ArcartX_Chronos` 文件夹,请检查:
- 插件文件是否正确上传
- 服务端控制台是否有报错信息
- ArcartX 插件是否已正确安装
### 配置授权码
打开 `plugins/ArcartX_Chronos/license.yml` 文件:
```yaml
# 填写您的授权信息
licenseId: 114514 # 替换为您的授权码ID
licenseKey: KEY-xXxxXXx # 替换为您的授权码KEY
```
**编辑器推荐:** 使用 `Visual Studio Code`、`Notepad++` 或其他支持 YAML 语法高亮的编辑器。
### 重启验证
在服务端后台输入 `stop` 命令重启服务器,观察控制台输出:
```log
[03:13:26 INFO]: ___ _ _____ _ _ _ _
[03:13:26 INFO]: / __\_ _ / |___ /_\ _ __| |_(_)___| |_
[03:13:26 INFO]: /__\// | | | | | / //_\\| '__| __| / __| __|
[03:13:26 INFO]: / \/ \ |_| |_ | | / / _ \ | | |_| \__ \ |_
[03:13:26 INFO]: \_____/\__, (_) |_|/_/\_/ \_/_| \__|_|___/\__|
[03:13:26 INFO]: |___/
[03:13:26 INFO]: ♦ ArcartX-Chronos | 信息: 欢迎使用 ArcartX-Chronos
[03:13:26 INFO]: ♦ ArcartX-Chronos | 信息: 开始加载
[03:13:26 INFO]: ♦ ArcartX-Chronos | 信息: 加载完成
```
如果看到 **加载完成** 的提示,说明安装成功!
---
## 验证安装
安装成功后,你可以通过以下方式验证:
### 查看控制台输出
成功加载时,控制台会显示:
- 加载的按键配置数量
- 注册的控制器数量
- 注册的客户端按键
```log
[03:13:26 INFO]: ♦ ArcartX-Chronos | 信息: 按键分类: 克洛诺斯
[03:13:26 INFO]: ♦ ArcartX-Chronos | 信息: 加载1个按键配置
[03:13:26 INFO]: ♦ ArcartX-Chronos | 信息: 注册控制器idle
[03:13:26 INFO]: ♦ ArcartX-Chronos | 信息: 加载1个控制器配置
[03:13:26 INFO]: ♦ ArcartX-Chronos | 信息: 注册动作控制器-> idle
```
### 测试指令
在服务端或游戏内输入:
```
/ac
```
如果显示指令帮助列表,说明插件已正常运行。
---
## 常见问题
**问题:插件未加载**
可能原因:
1. ArcartX 插件未安装
2. 服务端版本不支持
3. 授权码无效或已过期
**问题:授权验证失败**
解决方案:
1. 检查 `licenseId` 和 `licenseKey` 是否正确
2. 确认服务器能够访问网络
3. 联系社区管理员确认授权状态
---
## 下一步
安装完成后,请继续阅读:
了解插件的文件结构
配置默认控制器和基本选项
---
## 配置目录结构
URL: https://wiki.arcartx.com/docs/chronos/3_config
## 目录结构
安装完成后,`plugins/ArcartX_Chronos` 目录结构如下:
---
## 文件说明
| 文件/文件夹 | 类型 | 作用 | 重要程度 |
|-----------------------|------|--------------|--------|
| **📁 controllers** | 文件夹 | 存放动作控制器配置文件 | ⭐⭐⭐ 核心 |
| **📄 keybinding.yml** | 配置文件 | 注册自定义按键用于连招链 | ⭐⭐ 常用 |
| **📄 license.yml** | 配置文件 | 许可证授权配置 | ⭐ 一次性 |
| **📄 setting.yml** | 配置文件 | 基本设置(默认控制器等) | ⭐⭐ 常用 |
---
## 详细说明
### 📁 controllers 文件夹
这是 Chronos 最核心的配置目录。每个 `.yml` 文件都是一个独立的**动作控制器**配置。
```mermaid
flowchart TB
subgraph Controllers["controllers 文件夹"]
A["idle.yml
待机控制器"]
B["sword.yml
剑士控制器"]
C["bow.yml
弓箭手控制器"]
D["..."]
end
Controllers --> E["控制器ID = 文件名"]
```
**控制器ID 就是文件名!** 例如创建 `sword.yml`,控制器ID 就是 `sword`。
**控制器配置包含:**
- 基础设置(模型、输入缓冲等)
- 状态声明(所有动作的定义)
- 连招链(动作之间的派生关系)
详细配置请参考 [动作控制器](/docs/chronos/7_controller)。
---
### 📄 keybinding.yml
注册自定义按键,用于连招链中的 `KEY_PRESS` 和 `KEY_HOLD` 输入类型。
```yaml
# 客户端按键分类名称
category: "克洛诺斯"
# 按键定义
keys:
战技1: "X" # 按键名称: 默认键位
战技2: "Q"
闪避: "SPACE"
```
这里注册的按键允许玩家在客户端自定义绑定。
详细配置请参考 [注册按键](/docs/chronos/6_key)。
---
### 📄 license.yml
存放授权信息,安装时配置一次即可。
```yaml
licenseId: 114514
licenseKey: KEY-xXxxXXx
```
---
### 📄 setting.yml
插件的基本设置。
```yaml
# 默认控制器ID
default_controller: "idle"
# 通过主手物品自动切换控制器
switch_by_main_hand:
enable: false
path: "controller"
```
详细配置请参考 [基本设置](/docs/chronos/5_setting)。
---
## 配置文件关系
理解各配置文件之间的关系:
```mermaid
flowchart TB
Setting["setting.yml
基本设置"] --> |"指定默认控制器"| Controller
subgraph Controller["controllers/*.yml"]
C1["状态定义"]
C2["连招链"]
C3["输入配置"]
end
Keybinding["keybinding.yml
按键注册"] --> |"提供按键ID"| C3
Controller --> |"应用到"| Player["玩家"]
```
---
## 快速导航
配置默认控制器和自动切换
定义自定义按键
核心配置:状态和连招链
---
## 指令
URL: https://wiki.arcartx.com/docs/chronos/4_command
## 指令概览
Chronos 提供了简洁的指令系统来管理玩家的动作控制器。
### 指令前缀
可以使用以下任意前缀:
- `/arcartx_chronos` - 完整前缀
- `/ac` - 简写前缀(推荐)
---
## 指令列表
| 指令 | 作用 | 权限 |
|------------------------|----------|----|
| `/ac set <控制器ID> <玩家>` | 为玩家设置控制器 | OP |
| `/ac remove <玩家>` | 移除玩家的控制器 | OP |
| `/ac reload` | 重载所有配置文件 | OP |
在后台输入 `/ac` 可以查看指令帮助:
```log
[18:44:55 INFO]: ♦ ArcartX-Chronos | 信息: 指令列表
[18:44:55 INFO]: ♦ ArcartX-Chronos | 信息: - /arcartx_chronos set - 设置玩家控制器
[18:44:55 INFO]: ♦ ArcartX-Chronos | 信息: - /arcartx_chronos remove - 移除玩家控制器
[18:44:55 INFO]: ♦ ArcartX-Chronos | 信息: - /arcartx_chronos reload - 重载
```
---
## 详细用法
### set - 设置控制器
为指定玩家设置动作控制器。
**语法:**
```
/ac set <控制器ID> <玩家名称>
```
**参数说明:**
| 参数 | 说明 |
|---------|------------------------------------|
| `控制器ID` | `controllers` 文件夹中的 yml 文件名(不含扩展名) |
| `玩家名称` | 在线玩家的游戏名 |
**示例:**
```bash
# 为玩家 Steve 设置剑士控制器
/ac set sword Steve
# 为玩家 Alex 设置弓箭手控制器
/ac set bow Alex
```
**控制器ID 就是文件名!** 如果你的配置文件是 `controllers/sword.yml`,那么控制器ID 就是 `sword`。
---
### remove - 移除控制器
移除指定玩家的当前控制器。
**语法:**
```
/ac remove <玩家名称>
```
**示例:**
```bash
# 移除玩家 Steve 的控制器
/ac remove Steve
```
移除控制器后,玩家将无法使用 Chronos 的动作系统,直到重新设置控制器。
---
### reload - 重载配置
重新加载所有配置文件,无需重启服务器。
**语法:**
```
/ac reload
```
**重载后控制台输出示例:**
```log
[18:20:32 INFO]: ♦ ArcartX-Chronos | 信息: 加载1个控制器配置
[18:20:32 INFO]: ♦ ArcartX-Chronos | 信息: 注册动作客户端按键-> 战技1
[18:20:32 INFO]: ♦ ArcartX-Chronos | 信息: 注册动作客户端按键-> 战技2
[18:20:32 INFO]: ♦ ArcartX-Chronos | 信息: 注册动作控制器-> sword
[18:20:32 INFO]: ♦ ArcartX-Chronos | 信息: 注册动作控制器-> bow
```
**调试技巧:** 重载后查看控制台输出,可以确认:
- 有多少个控制器被加载
- 注册了哪些按键
- 各控制器的ID
---
## 使用流程
典型的工作流程:
```mermaid
flowchart LR
A["编辑配置文件"] --> B["/ac reload"]
B --> C["查看控制台确认加载"]
C --> D["/ac set 控制器 玩家"]
D --> E["测试动作效果"]
E --> |"需要调整"| A
```
---
## 常见问题
**问题:找不到控制器ID**
确认步骤:
1. 检查文件是否在 `controllers` 文件夹中
2. 检查文件扩展名是否为 `.yml`
3. 执行 `/ac reload` 重载配置
4. 查看控制台输出确认控制器已注册
**问题:设置控制器后无效果**
可能原因:
1. 客户端未安装 ArcartX Mod
2. 服务端状态名与客户端控制器不匹配
3. 连招链配置有误
---
## 通过 API 使用
除了指令,你也可以通过 Java API 来管理控制器:
```java
// 获取 API
ChronosAPI api = ChronosAPI.getInstanceAPI();
// 为玩家设置控制器
api.setPlayerController(player, "sword");
// 获取玩家当前控制器ID
String controllerId = api.getPlayerControllerId(player);
// 移除玩家控制器
api.removePlayerController(player);
```
详细 API 请参考 [API/EVENT](/docs/chronos/9_api)。
---
## 基本设置
URL: https://wiki.arcartx.com/docs/chronos/5_setting
## 配置文件
在插件目录下打开 `setting.yml` 文件:
```yaml
# 默认控制器ID
default_controller: "idle"
# 通过主手物品切换控制器
switch_by_main_hand:
# 是否启用自动切换
enable: false
# NBT路径,多层使用点号分隔
path: "controller"
```
---
## 配置项详解
### default_controller - 默认控制器
```yaml
default_controller: "idle"
```
| 属性 | 说明 |
|---------|-----------------------------|
| **作用** | 玩家登录服务器时自动应用的控制器 |
| **值** | 控制器ID(controllers 文件夹中的文件名) |
| **默认值** | `idle` |
**重要:** Chronos 的所有功能都建立在控制器之上。玩家必须拥有一个控制器,才能使用动作系统。
**示例配置:**
```yaml
# 所有玩家默认使用待机控制器
default_controller: "idle"
# 或者让所有玩家默认使用剑士控制器
default_controller: "sword"
```
---
### switch_by_main_hand - 自动切换控制器
通过玩家手持物品的 NBT 数据自动切换控制器。
```yaml
switch_by_main_hand:
enable: false
path: "controller"
```
| 属性 | 说明 |
|------------|------------------|
| **enable** | 是否启用此功能 |
| **path** | NBT 数据路径,多层用点号分隔 |
**工作原理:**
```mermaid
flowchart TB
A["玩家切换手持物品"] --> B{"检查 NBT"}
B -->|"有 controller 标签"| C["读取标签值"]
C --> D["切换到对应控制器"]
B -->|"无 controller 标签"| E["回到默认控制器"]
```
**示例:**
假设你有一把剑,NBT 中包含:
```yaml
# 物品 NBT 结构
{
controller: "sword"
}
```
当玩家手持这把剑时,会自动切换到 `sword` 控制器。
**多层路径:**
```yaml
switch_by_main_hand:
enable: true
path: "arcartx.weapon.controller" # 多层NBT路径
```
对应的物品 NBT:
```yaml
{
arcartx: {
weapon: {
controller: "sword"
}
}
}
```
---
## 下一步
配置自定义按键
创建你的第一个控制器
---
## 注册按键
URL: https://wiki.arcartx.com/docs/chronos/6_key
## 概述
`keybinding.yml` 用于注册自定义按键,这些按键可以在连招链配置中使用。
```mermaid
flowchart LR
A["keybinding.yml
注册按键"] --> B["控制器配置
使用按键ID"]
B --> C["客户端
玩家自定义绑定"]
```
---
## 配置文件
在插件目录下打开 `keybinding.yml` 文件:
```yaml
# 客户端中按键位于哪个分区
category: "克洛诺斯"
# 按键定义
keys:
# 按键名称: 默认键位
战技1: "X"
战技2: "Q"
```
---
## 配置项详解
### category - 按键分类
```yaml
category: "克洛诺斯"
```
| 属性 | 说明 |
|------|------|
| **作用** | 在客户端按键设置中显示的分类名称 |
| **值** | 任意字符串 |
玩家在客户端的"按键设置"界面中,可以找到这个分类下的所有按键。
---
### keys - 按键定义
```yaml
keys:
战技1: "X"
战技2: "Q"
闪避: "LEFT_ALT"
格挡: "V"
```
| 格式 | 说明 |
|------|------|
| **按键名称** | 你自定义的名称,用于连招链配置中引用 |
| **默认键位** | 按键的默认绑定,玩家可以在客户端修改 |
**注册的按键允许玩家在客户端自定义绑定。** 这意味着玩家可以根据自己的习惯修改这些按键。
---
## 在连招链中使用
注册的按键可以在控制器配置的连招链中使用:
```yaml
# keybinding.yml 中注册
keys:
战技1: "X"
# 控制器配置中使用
combo:
战技A:
input:
type: KEY_PRESS # 或 KEY_HOLD
value: "战技1" # 引用按键名称
```
---
## 输入类型对比
按键支持3种输入类型:
| 输入类型 | 说明 | 触发条件 |
|--------------------|-------|-----------------|
| `KEY_PRESS` | 按键点击 | 按下按键时立即触发 |
| `KEY_HOLD` | 按键长按 | 按住按键 ≥100ms 后触发 |
| `KEY_HOLD_RELEASE` | 长按后释放 | 长按后松开时触发 |
**示例:**
```yaml
combo:
# 点击 X 键触发普通技能
普通技能:
input:
type: KEY_PRESS
value: "战技1"
# 长按 X 键触发蓄力技能
蓄力技能:
input:
type: KEY_HOLD
value: "战技1"
# 长按后释放触发释放技能
释放技能:
input:
type: KEY_HOLD_RELEASE
value: "战技1"
```
---
## 可用键位
你可以使用以下键位作为默认绑定:
### 字母键
`A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M` `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z`
### 数字键
`0` `1` `2` `3` `4` `5` `6` `7` `8` `9`
### 功能键
`F1` `F2` `F3` `F4` `F5` `F6` `F7` `F8` `F9` `F10` `F11` `F12`
### 特殊键
| 键位 | 说明 |
|-----------------|--------|
| `SPACE` | 空格键 |
| `LEFT_SHIFT` | 左Shift |
| `RIGHT_SHIFT` | 右Shift |
| `LEFT_CONTROL` | 左Ctrl |
| `RIGHT_CONTROL` | 右Ctrl |
| `LEFT_ALT` | 左Alt |
| `RIGHT_ALT` | 右Alt |
| `TAB` | Tab键 |
| `CAPS_LOCK` | 大写锁定 |
| `ENTER` | 回车键 |
| `BACKSPACE` | 退格键 |
### 小键盘
`NUMPAD_0` 到 `NUMPAD_9`、`NUMPAD_ADD`、`NUMPAD_SUBTRACT` 等
完整的键位列表请参考:[客户端按键ID表](/docs/core/5_key/4_key_name)
---
## 下一步
在连招链中使用这些按键
查看完整的键位列表
---
## 动作控制器
URL: https://wiki.arcartx.com/docs/chronos/7_controller
## 概念
客户端控制器是一个状态机,它会根据玩家的状态来切换不同的动画。
关于这一部分就不在这里赘述了,详细介绍你可以在 [客户端动作控制器](/docs/core/10_controller/2_controller) 中了解。
* Chronos 为你提供了状态机,在后文中我们会称其为 `服务端状态机`
* ArcartX 同样提供了状态机,但我们会称其为 `客户端状态机`
* 你需要结合前后端状态机,才能实现完整的功能。
## 注册控制器
你可以在插件目录下的 `📁controllers` 文件夹中随意创建 `xxx.yml` 文件。
**每一个**文件都会被 Chronos 加载,并注册为一个动作控制器。
控制器ID 就是你创建的 `xxx.yml` 文件的文件名。
Chronos 为你提供了一个默认配置文件以供参考学习。
但是由于文件太长了,我们分段展示。
---
### 基础设置
这里几乎没有什么可以讲的,配置文件的注释已经非常详细。
``` yaml
# 控制器基础设置
setting:
# 客户端控制器ID
client_controller_id: "idle"
# 继承某个控制器的所有状态(可选)支持多层继承
extends: ""
# 设为该控制器后设置玩家模型,如果不需要则留空或者删除该项
# 不过请注意,这个留空并非是不启用模型,而是不进行任何操作,如果你之前设置过模型,这里留空将不会移除之前的模型
model: "steve"
model_scale: 1.0
# 启用原版左右键效果[不建议开启,这个开了将允许原版左键攻击和右键交互]
enable_use: false
# 输入缓冲设置
input_buffer:
enabled: true # 是否启用
max_size: 3 # 最大缓冲数量
lifetime: 300 # 输入有效期(ms)
# 触发器
action:
# 初始化 (这里顺便讲一下,每个玩家设置新的控制器会新建一个独立的上下文,你可以存储各种状态来辅助上下文条件判断等)
init: |-
var.attackTag = false
```
**输入缓冲参数说明:**
- `enabled`: 是否启用输入缓冲
- `max_size`: 最多缓冲多少个输入
- `lifetime`: 输入的有效期(毫秒),超过这个时间的输入会被丢弃
---
### 状态声明
在文件中,你需要声明你控制器中所有可能会用到的状态。
状态声明必须位于 `state` 节点下。
顺序不分先后,这里只是注册状态,后续你可以在连招链中引用这些状态。
示例:
``` yaml
...
# 省略基本配置项,你可以参考上面的示例
state:
状态ID:
# 客户端控制器对应的子控制器名称
controller: "main"
# 客户端子控制器下的状态名称
stateName: "attack1"
# 播放速度 支持Glimmer【注意,速度会影响所有时间窗口以及执行时间线】
speed: "1"
# 持续时间[ms] 支持Glimmer
duration: "500"
# 缓冲释放衔接时间点[ms],-1表示在派生窗口内立即衔接(默认),>=0表示存储预输入并在到达该时间点时衔接
# 例如: buffer_at 400 表示在400ms时如果有预输入则衔接,这样可以实现"预输入"效果
buffer_at: -1
# 状态所属分组
group: "攻击"
# 是否开启蓄力 开启后动作结束将对玩家上下文赋值蓄力时间[ms] 通过self.getChargeTime() 获取
charge: false
```
### 状态进入条件
每个状态都可以配置进入条件,只有满足条件时才能进入该状态:
``` yaml
state:
状态ID:
...
# 状态进入条件
conditions:
# Glimmer 表达式 返回布尔类型
expression: "self.getFood() >= 6 && !self.isFlying()"
# 如果处于以下组的状态时,无法进入该状态
blocked_group:
- "受控"
- "特殊运动"
```
- `expression`: 使用 Glimmer 表达式进行动态判断
- `blocked_group`: 当玩家当前处于这些状态组时,无法进入该状态
---
### 冷却时间
``` yaml
# 状态声明
state:
# 注意这个名字不要重复,后续作为状态ID
状态ID:
...
# 省略基本配置项,你可以参考上面的示例
# 冷却设置
cooldown:
# 是否开启冷却
enable: false
# 冷却时间 支持Glimmer
time: "0"
# 冷却组
group: "-"
```
**冷却组的作用:** 同一个冷却组的状态共享冷却时间。例如,所有闪避动作可以放在 "dodge" 组,这样玩家无论用哪种方式闪避,都会进入同一个冷却。
---
### 窗口期
指在一个状态的生命周期内,玩家可以在哪个时间段内位于窗口。
- **生命周期**:状态基本设置中的 `duration` 结束之前都是 `生命周期` 内的时间。
- **开始时间**:窗口子属性中的 `start`,表示窗口开始的时间点。
- **结束时间**:窗口子属性中的 `end`,表示窗口结束的时间点。
- **时间段**:从 `开始时间[ms]` 到 `结束时间[ms]` 之间的这段时间。
- **注意,这些周期都会被speed属性影响。**
**可用窗口表**:
| 窗口名称 | 翻译 | 作用 |
|-------------|-----|----------------------------|
| cancel | 取消 | 比如重击前摇 此时可以通过发起其它连招链的输入来取消 |
| derive | 派生 | 此时状态会接收下一步输入,来判断下一步转换为哪个状态 |
| invincible | 无敌帧 | 这个时间内是无敌的,可用于闪避 |
| super_armor | 霸体 | 这个时间内不会进入受控状态 |
`invincible` 无敌帧有一个额外的属性 `invincible_tag_duration`,用于设置成功规避伤害标签持续时间,用于做完美闪避反击动作,当无敌窗口期成功阻止伤害,会对玩家添加该持续时间的标签,使 `self.isInvincibleTag()` 的返回值为true。
#### 单时间段配置
最基础的窗口配置方式,设置一个开始时间和结束时间:
``` yaml
windows:
derive:
start: 300 # 开始时间 (ms)
end: 450 # 结束时间 (ms)
```
#### 多时间段配置
支持在一个状态中设置多个激活时间段,适用于复杂的动作设计:
``` yaml
windows:
# 取消窗口 - 开始和结束时都可取消
cancel:
ranges:
- start: 0
end: 100
- start: 400
end: 500
# 无敌帧 - 多段无敌
invincible:
ranges:
- start: 50
end: 200
- start: 300
end: 350
invincible_tag_duration: 500 # 无敌标记持续时间
```
#### 窗口时间线示例
理解窗口在状态生命周期中的分布:
```mermaid
gantt
title 闪避状态窗口时间线 (duration: 400ms)
dateFormat X
axisFormat %L ms
section 无敌帧
无敌1 :active, 50, 200
无敌2 :active, 300, 350
section 派生窗口
派生 :crit, 300, 380
section 取消窗口
取消 :380, 400
```
#### 完整窗口配置示例
``` yaml
# 状态声明
state:
# 注意这个名字不要重复,后续作为状态ID
状态ID:
...
# 省略基本配置项,你可以参考上面的示例
# 窗口阶段【如果不需要哪个窗口阶段,直接删除对应阶段的配置项】
windows:
# 取消窗口期 【比如重击前摇 此时可以通过发起其它连招链的输入来取消】
cancel:
# 开始时间[ms](对于该状态生命周期)
start: 0
# 结束时间[ms] 同上,这个开始结束时间,会结合运算上方设置的speed的结果,比如设置的速度是2,那么此时这个窗口期是0-50毫秒
end: 100
# 派生状态窗口期【此时状态会接收下一步输入,来判断下一步转换为哪个状态】
derive:
start: 300
end: 450
# 无敌帧【这个时间内是无敌的,用于闪避】
invincible:
start: 0
end: 50
# 成功规避伤害标签持续时间,用于做完美闪避反击动作,当无敌窗口期成功阻止伤害,会对玩家添加该持续时间的标签,使 self.isInvincibleTag() 的返回值为true
invincible_tag_duration: 1000
# 霸体【这个期间不会进入受控状态】
super_armor:
start: 0
end: 50
```
---
### 执行设置
在这里定义一些执行步骤,每个步骤都有一个开始时间 `at`,表示在这个时间点执行对应的表达式 `expression`。
你可以在这里定义多个节点,分类给自己看。
- 执行设置中的 `at` 节点表示开始时间,单位为毫秒。
- 执行设置中的 `at` 节点不能重复,重复的时间会相互覆盖,谁活下来就看运气了。
表达式:
- 支持Glimmer表达式,你可以在表达式中使用 `self` 来调用玩家上下文的方法。
- 例如:`self.dash(1.5, 0.3)` 表示设置自身的速度向量为水平轴1.5,垂直轴0.3。
示例:
``` yaml
# 状态声明
state:
# 注意这个名字不要重复,后续作为状态ID
状态ID:
...
# 省略基本配置项,你可以参考上面的示例
# 执行设置
execute:
# 这里可以设置多个步骤 会按照设置的at(开始时间)顺序执行
默认:
# 开始时间
at: 6
# 执行表达式 Glimmer
expression: ""
```
---
### 完整实例
``` yaml
# 注意这个名字不要重复,后续作为状态ID
近战1段:
# 客户端控制器对应的子控制器名称
controller: "main"
# 客户端子控制器下的状态名称
stateName: "attack1"
# 播放速度 支持Glimmer
speed: "1"
# 持续时间[ms] 支持Glimmer
duration: "500"
# 缓冲释放衔接时间点[ms],-1表示在派生窗口内立即衔接(默认),>=0表示存储预输入并在到达该时间点时衔接
# 例如: buffer_at 400 表示在400ms时如果有预输入则衔接,这样可以实现"预输入"效果
buffer_at: -1
# 状态所属分组
group: "攻击"
# 是否开启蓄力 开启后动作结束将对玩家上下文赋值蓄力时间[ms] 通过self.getChargeTime() 获取
charge: false
# 状态进入条件
conditions:
# Glimmer 表达式 返回布尔类型
expression: "true"
# 如果处于以下组的状态时,无法进入该状态
blocked_group:
- "受控"
- "特殊运动"
# 冷却设置
cooldown:
# 是否开启冷却
enable: false
# 冷却时间 支持Glimmer
time: "0"
# 冷却组
group: "-"
# 窗口阶段【如果不需要哪个窗口阶段,直接删除对应阶段的配置项】
windows:
# 取消窗口期 【比如重击前摇 此时可以通过发起其它连招链的输入来取消】
cancel:
# 开始时间[ms](对于该状态生命周期)
start: 0
# 结束时间[ms] 同上,这个开始结束时间,会结合运算上方设置的speed的结果,比如设置的速度是2,那么此时这个窗口期是0-50毫秒
end: 100
# 派生状态窗口期【此时状态会接收下一步输入,来判断下一步转换为哪个状态】
derive:
start: 300
end: 450
# 无敌帧【这个时间内是无敌的,用于闪避】
invincible:
start: 0
end: 50
# 成功规避伤害标签持续时间,用于做完美闪避反击动作,当无敌窗口期成功阻止伤害,会对玩家添加该持续时间的标签,使 self.isInvincibleTag() 的返回值为true
invincible_tag_duration: 1000
# 霸体【这个期间不会进入受控状态】
super_armor:
start: 0
end: 50
# 执行设置
execute:
# 这里可以设置多个步骤 会按照设置的at(开始时间)顺序执行
默认:
# 开始时间
at: 6
# 执行表达式 Glimmer
expression: ""
```
---
## 连招链
在 `combo` 节点下为状态定义一个输入类型,以及可以衔接到的下一个状态。
动作如何播放就取决于你设置状态的的输入类型。
### 输入类型
| 输入类型 | 翻译 | 作用 | 示例 |
|--------------------|---------|-------------------|--------------------------------------------------------------------|
| MOUSE_CLICK | 鼠标点击 | 点击鼠标左键或右键 | `LEFT` `RIGHT` |
| MOUSE_HOLD | 鼠标长按 | 长按鼠标左键或右键(≥100ms) | `LEFT` `RIGHT` |
| MOUSE_HOLD_RELEASE | 鼠标长按后释放 | 长按鼠标后释放 | `LEFT` `RIGHT` |
| KEY_PRESS | 按键按下 | 按下设定中的按键 | 对应 `keybinding` 中的 `keys` 字段,例如 `战技1` `战技2` |
| KEY_HOLD | 按键长按 | 长按设定中的按键(≥100ms) | 同上 |
| KEY_HOLD_RELEASE | 按键长按后释放 | 长按按键后释放 | 同上 |
| ACTION | 动作判断 | 跳跃、冲刺、下蹲等 | `JUMP` `SNEAK` `SPRINT` `SPRINT_LEFT` `SPRINT_RIGHT` `SPRINT_BACK` |
| AUTO | 自动衔接 | 状态结束后自动进入下一个状态 | - |
- `combo` 总节点,你的连招链需要写在这个节点下面。
- `input` 节点,对应了该连招会被什么触发。
- `cancel` 节点,对应了你在注册状态时写下的窗口期;表示取消连招,进入下一个链条。
- `derive` 节点,对应了你在注册状态时写下的窗口期;表示衔接哪些动作。
### 基础连招配置
最简单的连招链配置,按顺序派生:
``` yaml
# 连招链设置
combo:
# 这个名字对应上面的状态ID
近战1段:
# 输入
input:
# 输入类型 MOUSE_CLICK | MOUSE_HOLD | KEY_PRESS | KEY_HOLD | ACTION
type: MOUSE_CLICK
# 输入值
# MOUSE_CLICK -> LEFT RIGHT
# MOUSE_HOLD -> LEFT RIGHT
# KEY_PRESS -> 按键设定中对应的按键名
# KEY_HOLD -> 按键设定中对应的按键名
# ACTION -> JUMP SPRINT SPRINT_LEFT SPRINT_RIGHT SPRINT_BACK SNEAK
# 这个ACTION详细讲解下,分别是玩家进行下蹲输入、跳跃输入、冲刺输入(分别是前后左右,对于第三人称相机自由模式或者转向锁定期间,只会触发向前)
value: LEFT
derive:
近战2段:
input:
type: MOUSE_CLICK
value: LEFT
derive:
近战3段:
input:
type: MOUSE_CLICK
value: LEFT
近战重击:
input:
type: MOUSE_CLICK
value: RIGHT
```
---
## 组合输入模式
Chronos 支持三种组合输入模式,让你的连招系统更加丰富:
### OR 模式 - 多种触发方式
任意一个输入满足即可触发。适用于同一个动作有多种触发方式的场景:
``` yaml
闪避:
input:
mode: OR
inputs:
- type: ACTION
value: SPRINT
- type: ACTION
value: SPRINT_LEFT
- type: ACTION
value: SPRINT_RIGHT
- type: ACTION
value: SPRINT_BACK
```
**使用场景示例:** 玩家可以通过向任何方向冲刺来触发闪避动作,无需为每个方向单独配置。
### AND 模式 - 组合键
所有输入必须同时满足。适用于需要组合按键的高级技能:
``` yaml
蓄力重击:
input:
mode: AND
inputs:
- type: ACTION
value: SNEAK # 按住潜行
- type: MOUSE_HOLD
value: RIGHT # 同时长按右键
```
**使用场景示例:** 玩家需要同时按住潜行键和长按鼠标右键,才能触发蓄力重击。这适合设计高伤害但需要精确操作的技能。
### SEQUENCE 模式 - 搓招
按顺序在时间窗口内完成。适用于格斗游戏风格的搓招技能:
``` yaml
升龙拳:
input:
mode: SEQUENCE
time_window: 500 # 必须在500ms内完成
inputs:
- type: ACTION
value: SPRINT_BACK # 第1步: 后退
- type: ACTION
value: SPRINT # 第2步: 前冲
- type: MOUSE_CLICK
value: LEFT # 第3步: 攻击
```
**使用场景示例:** 玩家需要在500毫秒内依次输入:后退 → 前冲 → 攻击,才能触发升龙拳技能。这种设计让高级技能需要玩家掌握一定的操作技巧。
---
## 自动衔接 (AUTO)
状态结束后自动进入下一个状态,无需玩家输入:
``` yaml
combo:
冲刺斩:
input:
type: ACTION
value: SPRINT
derive:
冲刺斩收招:
input:
type: AUTO # 自动衔接,无需玩家输入
```
**使用场景示例:** 冲刺斩动作结束后自动进入收招动作,让动作衔接更加流畅自然。
---
## 完整连招示例
以下是一个包含多种输入模式的完整连招配置:
``` yaml
combo:
# 基础攻击链
攻击1段:
input:
type: MOUSE_CLICK
value: LEFT
derive:
攻击2段:
input:
type: MOUSE_CLICK
value: LEFT
闪避:
input:
mode: OR
inputs:
- type: ACTION
value: SPRINT
- type: ACTION
value: SPRINT_BACK
# 多方向闪避(根节点)
闪避:
input:
mode: OR
inputs:
- type: ACTION
value: SPRINT
- type: ACTION
value: SPRINT_LEFT
- type: ACTION
value: SPRINT_RIGHT
- type: ACTION
value: SPRINT_BACK
derive:
# 两个分支,根据顺序判断优先级
完美闪避反击:
input:
type: MOUSE_CLICK
value: LEFT
闪避反击:
input:
type: MOUSE_CLICK
value: LEFT
```
**派生优先级说明:** 当多个派生都满足条件时,按照配置的顺序判断优先级。上面的例子中,如果玩家处于无敌标记期间,会优先进入"完美闪避反击";否则进入普通的"闪避反击"。
---
## Glimmer 语句
URL: https://wiki.arcartx.com/docs/chronos/8_glimmer
## 概述
Glimmer 是 Chronos 的服务端表达式系统,用于在状态配置中编写动态逻辑。
**Glimmer vs Shimmer:** 两者语法完全相同,Glimmer 运行在服务端(Chronos),Shimmer 运行在客户端(ArcartX)。取不同的名字是为了方便区分。
**迁移说明:** 大部分 Glimmer 语句已从 Chronos 迁移至 ArcartX 本体。这意味着即使不安装 Chronos,ArcartX 本体也可以使用这些 Glimmer 语句(如 `dash`、`teleport` 系列、`sendUIPacket`、`getPlaceholder` 等)。以下文档中的语句在 ArcartX 本体中同样可用。
### 新增语句
以下语句为新版本新增:
- `self.getPlaceholder(placeholder)` — 获取 PlaceholderAPI 占位符的值,参数为占位符字符串,返回解析后的字符串
- `self.sendUIPacket(uiID, handlerName, data)` — 向玩家发送 UI 通讯包,参数为 UI ID、处理器名称、包内容字符串
- `self.dashAdvanced(forward, strafe, vertical)` — 高级冲刺,参数为前后力度(正值前/负值后)、左右力度(正值右/负值左)、垂直力度
---
## 基本用法
在 Chronos 配置中,`self` 指代当前玩家对象:
```yaml
state:
攻击1段:
# 动态持续时间
duration: "500 * (1 - self.getAttackSpeed())"
# 动态速度
speed: "1 + var.speedBonus"
# 进入条件
conditions:
expression: "self.getFood() >= 6 && !self.isFlying()"
# 执行点
execute:
冲刺:
at: 100
expression: "self.dash(1.5, 0.3)"
```
---
## 使用场景
### 1. 条件表达式
控制状态是否可以进入:
```yaml
conditions:
expression: "self.getFood() >= 3 && self.isOnGround()"
```
### 2. 动态数值
根据玩家状态计算持续时间、速度等:
```yaml
duration: "600 - self.getChargeTime() * 0.5"
speed: "1.0 + var.attackSpeedBonus"
```
### 3. 执行动作
在状态执行过程中触发效果:
```yaml
execute:
前冲:
at: 50
expression: "self.dash(2.0, 0.2)"
攻击判定:
at: 150
expression: "self.castMythicMobSkill('slash_damage', 1.0)"
```
---
## 变量系统
你可以使用 `var.` 前缀来存储和读取自定义变量:
```yaml
setting:
action:
init: |-
var.comboCounter = 0
var.attackTag = false
state:
攻击1段:
execute:
设置连击:
at: 100
expression: "var.comboCounter = 1"
```
---
## 实用示例
### 闪避冲刺
```yaml
闪避:
execute:
前冲:
at: 50
expression: "self.dash(1.5, 0.1)"
```
### 跳跃攻击
```yaml
跳斩:
conditions:
expression: "self.isAfterJump()" # 只能在跳跃后触发
execute:
俯冲:
at: 100
expression: "self.dive(1.0)"
```
### 蓄力判定
```yaml
蓄力释放:
execute:
判定伤害:
at: 50
expression: |-
var.power = self.getChargeTime() / 1000
self.castMythicMobSkill("charge_attack", var.power)
```
---
## 语句参考
## 战斗相关语句 (EntityCombat)
### attack
- **说明:** 使对象攻击指定生物
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|--------|--------------|------|
| living | LivingEntity | 攻击目标 |
- **使用方式:** `entity.attack(living)`
- **返回值:** 无
---
### setHealth
- **说明:** 设置对象的生命值
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|--------|--------|-------|
| amount | double | 生命值数值 |
- **使用方式:** `entity.setHealth(20.0)`
- **返回值:** 无
---
### setFire
- **说明:** 设置对象的着火时间
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|-------|-----|------------------------|
| ticks | int | 着火时间(tick,20tick = 1秒) |
- **使用方式:** `entity.setFire(100)`
- **返回值:** 无
---
## 药水效果语句 (EntityEffect)
### addPotionEffect
- **说明:** 为对象添加药水效果
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|-----------|--------|---------------|
| id | String | 药水效果ID(见下方列表) |
| duration | int | 持续时间(tick) |
| amplifier | int | 效果等级(0为1级) |
- **使用方式:** `entity.addPotionEffect("speed", 200, 1)`
- **返回值:** 无
- **可用药水效果ID列表:**
| 增益效果 | 中文名 | 负面效果 | 中文名 |
|---------------------|-------|----------------|------|
| speed | 速度 | slowness | 缓慢 |
| haste | 急迫 | mining_fatigue | 挖掘疲劳 |
| strength | 力量 | instant_damage | 瞬间伤害 |
| instant_health | 瞬间治疗 | nausea | 反胃 |
| jump_boost | 跳跃提升 | blindness | 失明 |
| regeneration | 生命恢复 | hunger | 饥饿 |
| resistance | 抗性提升 | weakness | 虚弱 |
| fire_resistance | 防火 | poison | 中毒 |
| water_breathing | 水下呼吸 | wither | 凋零 |
| invisibility | 隐身 | glowing | 发光 |
| night_vision | 夜视 | levitation | 飘浮 |
| health_boost | 生命提升 | unluck | 霉运 |
| absorption | 伤害吸收 | bad_omen | 不祥之兆 |
| saturation | 饱和 | | |
| luck | 幸运 | | |
| slow_falling | 缓降 | | |
| conduit_power | 潮涌能量 | | |
| dolphins_grace | 海豚的恩惠 | | |
| hero_of_the_village | 村庄英雄 | | |
---
### removePotionEffect
- **说明:** 移除对象的指定药水效果
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|------------|--------|--------|
| effectName | String | 药水效果ID |
- **使用方式:** `entity.removePotionEffect("SPEED")`
- **返回值:** 无
---
### clearPotionEffect
- **说明:** 清除对象所有药水效果
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.clearPotionEffect()`
- **返回值:** 无
---
### hasPotionEffect
- **说明:** 检查对象是否拥有指定药水效果
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|------------|--------|--------|
| effectName | String | 药水效果ID |
- **使用方式:** `entity.hasPotionEffect("SPEED")`
- **返回值:** boolean(是否拥有该效果)
---
### getPotionEffectDuration
- **说明:** 获取对象指定药水效果的剩余持续时间
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|------------|--------|--------|
| effectName | String | 药水效果ID |
- **使用方式:** `entity.getPotionEffectDuration("SPEED")`
- **返回值:** int(剩余时间tick,无效果返回0)
---
### getPotionEffectAmplifier
- **说明:** 获取对象指定药水效果的等级
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|------------|--------|--------|
| effectName | String | 药水效果ID |
- **使用方式:** `entity.getPotionEffectAmplifier("SPEED")`
- **返回值:** int(效果等级,无效果返回 -1,无效药水名称返回 0)
---
## 实体信息语句 (EntityInfo)
### isJumping
- **说明:** 检查对象是否正在跳跃
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.isJumping()`
- **返回值:** boolean
此语句由 Chronos 插件提供,需要安装 Chronos 才可使用。
---
### isInWater
- **说明:** 检查对象是否在水中
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.isInWater()`
- **返回值:** boolean
---
### isFallFlying
- **说明:** 检查对象是否正在鞘翅滑翔
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.isFallFlying()`
- **返回值:** boolean
---
### isSwimming
- **说明:** 检查对象是否正在游泳
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.isSwimming()`
- **返回值:** boolean
---
### isInLava
- **说明:** 检查对象是否在岩浆中
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.isInLava()`
- **返回值:** boolean
此语句由 Chronos 插件提供,需要安装 Chronos 才可使用。
---
### isSleeping
- **说明:** 检查对象是否正在睡觉
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.isSleeping()`
- **返回值:** boolean
---
### isOnGround
- **说明:** 检查对象是否在地面上
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.isOnGround()`
- **返回值:** boolean
---
### getPosX
- **说明:** 获取对象的X坐标
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.getPosX()`
- **返回值:** double
---
### getPosY
- **说明:** 获取对象的Y坐标
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.getPosY()`
- **返回值:** double
---
### getPosZ
- **说明:** 获取对象的Z坐标
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.getPosZ()`
- **返回值:** double
---
### getYaw
- **说明:** 获取对象的水平朝向角度
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.getYaw()`
- **返回值:** float
---
### getPitch
- **说明:** 获取对象的垂直朝向角度
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.getPitch()`
- **返回值:** float
---
### getAir
- **说明:** 获取对象的剩余氧气值
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.getAir()`
- **返回值:** int
---
### getHealth
- **说明:** 获取对象当前生命值
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.getHealth()`
- **返回值:** double
---
### getMaxHealth
- **说明:** 获取对象最大生命值
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.getMaxHealth()`
- **返回值:** double
---
## 移动相关语句 (EntityMovement)
### teleportForward
- **说明:** 向前方传送指定距离(自动寻找安全位置)
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|----------|--------|---------|
| distance | double | 传送距离(格) |
- **使用方式:** `entity.teleportForward(5.0)`
- **返回值:** 无
---
### teleportBack
- **说明:** 向后方传送指定距离(自动寻找安全位置)
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|----------|--------|---------|
| distance | double | 传送距离(格) |
- **使用方式:** `entity.teleportBack(5.0)`
- **返回值:** 无
---
### teleportLeft
- **说明:** 向左方传送指定距离(自动寻找安全位置)
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|----------|--------|---------|
| distance | double | 传送距离(格) |
- **使用方式:** `entity.teleportLeft(5.0)`
- **返回值:** 无
---
### teleportRight
- **说明:** 向右方传送指定距离(自动寻找安全位置)
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|----------|--------|---------|
| distance | double | 传送距离(格) |
- **使用方式:** `entity.teleportRight(5.0)`
- **返回值:** 无
---
### teleportUp
- **说明:** 向上方传送指定距离(自动寻找安全位置)
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|----------|--------|---------|
| distance | double | 传送距离(格) |
- **使用方式:** `entity.teleportUp(5.0)`
- **返回值:** 无
---
### teleportDown
- **说明:** 向下方传送指定距离(自动寻找安全位置)
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|----------|--------|---------|
| distance | double | 传送距离(格) |
- **使用方式:** `entity.teleportDown(5.0)`
- **返回值:** 无
---
### dash
- **说明:** 向前方冲刺(设置速度向量)
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|------------|--------|------|
| horizontal | double | 水平速度 |
| vertical | double | 垂直速度 |
- **使用方式:** `entity.dash(1.5, 0.3)`
- **返回值:** 无
---
### dashBack
- **说明:** 向后方冲刺(设置速度向量)
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|------------|--------|------|
| horizontal | double | 水平速度 |
| vertical | double | 垂直速度 |
- **使用方式:** `entity.dashBack(1.5, 0.3)`
- **返回值:** 无
---
### dashLeft
- **说明:** 向左方冲刺(设置速度向量)
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|------------|--------|------|
| horizontal | double | 水平速度 |
| vertical | double | 垂直速度 |
- **使用方式:** `entity.dashLeft(1.5, 0.3)`
- **返回值:** 无
---
### dashRight
- **说明:** 向右方冲刺(设置速度向量)
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|------------|--------|------|
| horizontal | double | 水平速度 |
| vertical | double | 垂直速度 |
- **使用方式:** `entity.dashRight(1.5, 0.3)`
- **返回值:** 无
---
### jump
- **说明:** 使对象向上跳跃
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|-------|--------|------|
| force | double | 跳跃力度 |
- **使用方式:** `entity.jump(0.5)`
- **返回值:** 无
---
### dive
- **说明:** 使对象向下俯冲
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|-------|--------|------|
| force | double | 俯冲力度 |
- **使用方式:** `entity.dive(1.0)`
- **返回值:** 无
---
### bounce
- **说明:** 反弹对象速度(速度向量取反)
- **对象:** LivingEntity(生物)
- **参数:** 无
- **使用方式:** `entity.bounce()`
- **返回值:** 无
---
### dashAdvanced
- **说明:** 高级冲刺,可分别控制前后、左右、垂直三个方向的力度
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|----------|--------|----------------------|
| forward | double | 前后力度(正值前/负值后) |
| strafe | double | 左右力度(正值右/负值左) |
| vertical | double | 垂直力度 |
- **使用方式:** `entity.dashAdvanced(1.5, 0.5, 0.3)`
- **返回值:** 无
---
## 实体选择器语句 (EntitySelector)
以下实体选择器语句由 Chronos 插件提供,需要安装 Chronos 才可使用。
### getLivingEntitiesInRadius
- **说明:** 获取圆形范围内的所有生物实体
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|--------|--------|----|
| radius | double | 半径 |
- **使用方式:** `entity.getLivingEntitiesInRadius(10.0)`
- **返回值:** List\(范围内的生物列表)
---
### getLivingEntitiesInCone
- **说明:** 获取面前扇形范围内的生物实体
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|--------|--------|----------|
| radius | double | 半径 |
| angle | double | 扇形角度(度数) |
- **使用方式:** `entity.getLivingEntitiesInCone(10.0, 90.0)`
- **返回值:** List\(范围内的生物列表)
---
### getLivingEntitiesInBox
- **说明:** 获取面前矩形范围内的生物实体
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|--------|--------|----|
| width | double | 宽度 |
| length | double | 长度 |
| height | double | 高度 |
- **使用方式:** `entity.getLivingEntitiesInBox(5.0, 10.0, 3.0)`
- **返回值:** List\(范围内的生物列表)
---
### getLivingEntitiesInRing
- **说明:** 获取环形范围内的生物实体(内圈到外圈之间)
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|-------------|--------|-----|
| innerRadius | double | 内半径 |
| outerRadius | double | 外半径 |
- **使用方式:** `entity.getLivingEntitiesInRing(5.0, 10.0)`
- **返回值:** List\(范围内的生物列表)
---
### getNearestLivingEntity
- **说明:** 获取最近的生物实体
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|-------------|--------|--------|
| maxDistance | double | 最大搜索距离 |
- **使用方式:** `entity.getNearestLivingEntity(20.0)`
- **返回值:** LivingEntity(最近的生物,没有则返回null)
---
## 玩家信息语句 (PlayerInfo)
### isAfterJump
- **说明:** 检查玩家是否在跳跃后的时间窗口内
- **对象:** Player(玩家)
- **参数:** 无
- **使用方式:** `player.isAfterJump()`
- **返回值:** boolean
---
### isSprinting
- **说明:** 检查玩家是否正在疾跑
- **对象:** Player(玩家)
- **参数:** 无
- **使用方式:** `player.isSprinting()`
- **返回值:** boolean
---
### isSneaking
- **说明:** 检查玩家是否正在潜行
- **对象:** Player(玩家)
- **参数:** 无
- **使用方式:** `player.isSneaking()`
- **返回值:** boolean
---
### isFlying
- **说明:** 检查玩家是否正在飞行
- **对象:** Player(玩家)
- **参数:** 无
- **使用方式:** `player.isFlying()`
- **返回值:** boolean
---
### getFood
- **说明:** 获取玩家的饥饿值
- **对象:** Player(玩家)
- **参数:** 无
- **使用方式:** `player.getFood()`
- **返回值:** int(0-20)
---
### getPlaceholder
- **说明:** 获取 PlaceholderAPI 占位符的值
- **对象:** Player(玩家)
- **参数:**
| 参数名 | 类型 | 说明 |
|-------------|--------|----------|
| placeholder | String | 占位符字符串 |
- **使用方式:** `player.getPlaceholder("%player_level%")`
- **返回值:** String(解析后的字符串)
---
### getChargeTime
- **说明:** 获取玩家的蓄力时间
- **对象:** Player(玩家)
- **参数:** 无
- **使用方式:** `player.getChargeTime()`
- **返回值:** double
此语句由 Chronos 插件提供,需要安装 Chronos 才可使用。
---
### isInvincibleTag
- **说明:** 检查玩家是否处于无敌状态
- **对象:** Player(玩家)
- **参数:** 无
- **使用方式:** `player.isInvincibleTag()`
- **返回值:** boolean
此语句由 Chronos 插件提供,需要安装 Chronos 才可使用。
---
### getState
- **说明:** 获取玩家的当前状态ID
- **对象:** Player(玩家)
- **参数:** 无
- **使用方式:** `player.getState()`
- **返回值:** String
此语句由 Chronos 插件提供,需要安装 Chronos 才可使用。
---
## 玩家消息语句 (PlayerMessage)
### showTitle
- **说明:** 向玩家显示标题
- **对象:** Player(玩家)
- **参数:**
| 参数名 | 类型 | 说明 |
|----------|--------|------------|
| title | String | 主标题 |
| subtitle | String | 副标题 |
| fadeIn | int | 淡入时间(tick) |
| stay | int | 停留时间(tick) |
| fadeOut | int | 淡出时间(tick) |
- **使用方式:** `player.showTitle("主标题", "副标题", 10, 70, 20)`
- **返回值:** 无
---
### sendMessage
- **说明:** 向玩家发送聊天消息
- **对象:** Player(玩家)
- **参数:**
| 参数名 | 类型 | 说明 |
|---------|--------|------|
| message | String | 消息内容 |
- **使用方式:** `player.sendMessage("Hello World!")`
- **返回值:** 无
---
### sendUIPacket
- **说明:** 向玩家发送 UI 通讯包
- **对象:** Player(玩家)
- **参数:**
| 参数名 | 类型 | 说明 |
|-------------|--------|----------|
| uiID | String | UI ID |
| handlerName | String | 处理器名称 |
| data | String | 包内容字符串 |
- **使用方式:** `player.sendUIPacket("my_ui", "handler", "data")`
- **返回值:** 无
---
## MythicMobs集成 (MythicMob)
### castMythicMobSkill
- **说明:** 使对象释放MythicMobs技能
- **对象:** LivingEntity(生物)
- **参数:**
| 参数名 | 类型 | 说明 |
|-------|--------|------|
| name | String | 技能名称 |
| power | float | 技能强度 |
- **使用方式:** `entity.castMythicMobSkill("FireBall", 1.0)`
- **返回值:** 无
---
## 对象类型说明
| 对象类型 | 说明 |
|--------------|------------------|
| LivingEntity | 所有生物实体(包括玩家、怪物等) |
| Player | 仅限玩家 |
---
## 时间单位说明
- **tick**: Minecraft 的基本时间单位,1秒 = 20 tick
---
---
## API 与事件
URL: https://wiki.arcartx.com/docs/chronos/9_api
## 概述
Chronos 提供了完整的 Java API,让你可以在自己的插件中集成和扩展动作系统功能。
```mermaid
flowchart LR
A["你的插件"] --> B["ChronosAPI"]
B --> C["控制器管理"]
B --> D["状态控制"]
B --> E["事件监听"]
```
---
## 获取 API
```java
ChronosAPI api = ChronosAPI.getInstanceAPI();
```
---
## API 接口
### ChronosAPI 完整接口
```java
public interface ChronosAPI {
static ChronosAPI getInstanceAPI() {
return ChronosPlugin.getChronosAPI();
}
// 获取玩家存档上下文
Context getPlayerContext(Player player);
// 获取玩家冷却组剩余冷却时间
long getPlayerCooldown(Player player, String group);
// 获取玩家当前控制器ID
@Nullable
String getPlayerControllerId(Player player);
// 设置玩家当前控制器ID
void setPlayerController(Player player, String controllerId);
// 移除玩家当前控制器
void removePlayerController(Player player);
// 获取玩家当前状态ID
@Nullable
String getPlayerStateId(Player player);
// 获取玩家当前状态组ID
@Nullable
String getPlayerStateGroupId(Player player);
// 尝试进入状态,成功返回true,失败返回false
boolean tryEnterState(Player player, String stateId);
// 尝试进入受控状态,若玩家为霸体,该状态将进入失败
void tryEnterControlledState(Player player, String controlledStateId, double duration);
// 强行进入状态,不考虑任何条件,注意该状态必须在连招链的根节点声明
void forceEnterStateFromRootChain(Player player, String stateId);
}
```
---
## API 方法详解
### 控制器管理
| 方法 | 说明 | 返回值 |
|-----------------------------------|-------------|-------------------|
| `getPlayerControllerId(player)` | 获取玩家当前控制器ID | `String` 或 `null` |
| `setPlayerController(player, id)` | 为玩家设置控制器 | `void` |
| `removePlayerController(player)` | 移除玩家的控制器 | `void` |
**示例:根据职业设置控制器**
```java
public void setPlayerClass(Player player, String className) {
ChronosAPI api = ChronosAPI.getInstanceAPI();
switch (className) {
case "战士":
api.setPlayerController(player, "warrior");
break;
case "法师":
api.setPlayerController(player, "mage");
break;
case "弓箭手":
api.setPlayerController(player, "archer");
break;
}
}
```
---
### 状态查询
| 方法 | 说明 | 返回值 |
|------------------------------------|---------------|-------------------|
| `getPlayerStateId(player)` | 获取玩家当前状态ID | `String` 或 `null` |
| `getPlayerStateGroupId(player)` | 获取玩家当前状态组ID | `String` 或 `null` |
| `getPlayerCooldown(player, group)` | 获取冷却组剩余时间(ms) | `long` |
**示例:检查玩家是否在攻击状态**
```java
public boolean isPlayerAttacking(Player player) {
ChronosAPI api = ChronosAPI.getInstanceAPI();
String group = api.getPlayerStateGroupId(player);
return "攻击".equals(group);
}
```
---
### 状态控制
| 方法 | 说明 | 返回值 |
|------------------------------------------------------|--------------|-----------|
| `tryEnterState(player, stateId)` | 尝试进入状态(检查条件) | `boolean` |
| `tryEnterControlledState(player, stateId, duration)` | 尝试进入受控状态 | `void` |
| `forceEnterStateFromRootChain(player, stateId)` | 强制进入状态 | `void` |
**示例:让玩家进入受击状态**
```java
// MythicMobs 技能或其他插件中
public void onPlayerHit(Player player, double damage) {
ChronosAPI api = ChronosAPI.getInstanceAPI();
// 尝试让玩家进入受击状态,持续500ms
// 如果玩家处于霸体状态,则不会进入
api.tryEnterControlledState(player, "受击", 500);
}
```
**示例:强制触发技能**
```java
// 通过其他系统触发技能
public void castUltimate(Player player) {
ChronosAPI api = ChronosAPI.getInstanceAPI();
// 强制进入终极技能状态,无视所有条件
// 注意:该状态必须在连招链的根节点声明
api.forceEnterStateFromRootChain(player, "终极技能");
}
```
**`tryEnterState` vs `forceEnterStateFromRootChain`:**
- `tryEnterState`:会检查条件、冷却、blocked_group 等
- `forceEnterStateFromRootChain`:无视所有条件强制进入,但状态必须在 combo 根节点声明
---
### 上下文管理
| 方法 | 说明 | 返回值 |
|----------------------------|-------------------|-----------|
| `getPlayerContext(player)` | 获取玩家的 Glimmer 上下文 | `Context` |
**示例:读取自定义变量**
```java
public int getPlayerComboCount(Player player) {
ChronosAPI api = ChronosAPI.getInstanceAPI();
Context ctx = api.getPlayerContext(player);
}
```
---
## 事件系统
Chronos 提供了三个核心事件,可以通过 Bukkit 事件系统监听。
### PlayerEnterStateEvent
玩家进入状态时触发。
```java
public class PlayerEnterStateEvent extends Event {
@Getter
private final Player player;
@Getter
private final String stateId;
}
```
**监听示例:**
```java
@EventHandler
public void onEnterState(PlayerEnterStateEvent event) {
Player player = event.getPlayer();
String stateId = event.getStateId();
}
```
---
### PlayerLeaveStateEvent
玩家离开状态时触发。
```java
public class PlayerLeaveStateEvent extends Event {
@Getter
private final Player player;
@Getter @Nullable
private final String stateId;
}
```
**监听示例:**
```java
@EventHandler
public void onLeaveState(PlayerLeaveStateEvent event) {
Player player = event.getPlayer();
String stateId = event.getStateId();
}
```
---
### PlayerControllerChangeEvent
玩家控制器切换时触发。
```java
public class PlayerControllerChangeEvent extends Event {
@Getter
private final Player player;
@Getter @Nullable
private final String controllerId;
}
```
**监听示例:**
```java
@EventHandler
public void onControllerChange(PlayerControllerChangeEvent event) {
Player player = event.getPlayer();
String controllerId = event.getControllerId();
if (controllerId != null) {
player.sendMessage("§a已切换到控制器: " + controllerId);
} else {
player.sendMessage("§c已移除控制器");
}
}
```
---
## 集成示例
### 与 MythicMobs 集成
让怪物技能触发玩家受控状态:
```yaml
# MythicMobs 技能配置
击飞技能:
Skills:
- chronosControlledState{state=击飞;duration=800} @target
```
### 与职业插件集成
根据职业切换控制器:
```java
public class ClassChangeListener implements Listener {
@EventHandler
public void onClassChange(PlayerClassChangeEvent event) {
Player player = event.getPlayer();
String newClass = event.getNewClass();
ChronosAPI api = ChronosAPI.getInstanceAPI();
api.setPlayerController(player, newClass.toLowerCase());
}
}
```
---
## 注意事项
**线程安全:** Chronos API 应该在主线程中调用。如果从异步任务中调用,请使用 `Bukkit.getScheduler().runTask()` 包装。
**依赖声明:** 在你的 `plugin.yml` 中添加依赖:
```yaml
depend: [ArcartX_Chronos]
# 或者软依赖
softdepend: [ArcartX_Chronos]
```
---
## UIHandler:UI处理器
URL: https://wiki.arcartx.com/docs/server_api/10_ui_handler
## UIHandler
- `UIHandler` 是一个抽象类,提供了更优雅的UI管理方式。
- 它封装了UI的注册、生命周期回调和数据通信,你只需要继承它并实现回调方法即可。
- 创建继承实现之后,创建实例即注册UI
## 基本用法
```java
public class MyUI extends UIHandler {
private final JavaPlugin plugin;
public MyUI(JavaPlugin plugin) {
super("my_ui_id", new File(plugin.getDataFolder(), "ui/my_ui.yml"));
this.plugin = plugin;
}
@Override
public JavaPlugin getPlugin() {
return plugin;
}
@Override
public void onOpenPre(Player player) {
// UI打开前执行(服务端侧)
}
@Override
public void onOpenPost(Player player) {
// UI打开后执行(客户端确认打开后回调)
}
@Override
public void onClose(Player player) {
// UI关闭时执行
}
@Override
public void onPacket(Player player, String identifier, List data) {
// 收到客户端UI发来的数据包时执行
}
}
```
## 构造参数
- `identifier`: String — UI唯一标识
- `uiConfig`: File — UI配置文件
构造时会自动调用 `ArcartXUIRegistry.register()` 注册UI,并绑定生命周期回调。
## 生命周期回调
### `onOpenPre(player){:java}`
- UI打开前的回调,请求客户端打开UI之前执行,可在此处理数据或者发送早于控件create事件的预先包
- 详细解释下这个控件create之前的包是什么意思:
- UI打开流程:
- 收到打开请求
- 创建UI实例
- 检查有没有在UI打开之前就给该UI发送的包 如果有则调用对应处理器处理
- 创建该UI所有控件(即上文说的控件create)
- **参数**:`player`: Player — 目标玩家
- 适合在此处准备数据,发送控件create之前的包
### `onOpenPost(player){:java}`
- UI打开后的回调,客户端确认UI已打开后触发
- **参数**:`player`: Player — 目标玩家
- 适合在此处发送初始数据到UI
### `onClose(player){:java}`
- UI关闭时的回调
- **参数**:`player`: Player — 目标玩家
- 适合在此处清理资源、保存数据等
### `onPacket(player, identifier, data){:java}`
- 收到客户端UI发来的数据包时触发
- **参数**:
- `player`: Player — 发送数据的玩家
- `identifier`: String — 数据包标识
- `data`: List<String> — 数据内容
## 便捷方法
### `open(player){:java}`
- 为玩家打开此UI,会先调用 `onOpenPre`
- **参数**:`player`: Player — 目标玩家
- **调用示例**
```java
myUI.open(player);
```
### `close(player){:java}`
- 为玩家关闭此UI
- **参数**:`player`: Player — 目标玩家
- **调用示例**
```java
myUI.close(player);
```
### `sendPacket(player, packetHandler, packet){:java}`
- 向玩家客户端的UI发送数据包
- **参数**:
- `player`: Player — 目标玩家
- `packetHandler`: String — 处理器名称
- `packet`: Object — 数据包内容
- **调用示例**
```java
myUI.sendPacket(player, "update", dataMap);
```
### `sendRun(player, shimmerCode){:java}`
- 在玩家客户端的UI中执行Shimmer脚本
- **参数**:
- `player`: Player — 目标玩家
- `shimmerCode`: String — Shimmer脚本代码
- **调用示例**
```java
myUI.sendRun(player, "refreshList()");
```
---
## ControllerRegistry:控制器注册器
URL: https://wiki.arcartx.com/docs/server_api/11_controller_registry
## ControllerRegistry
- 控制器注册器用于注册和管理动作控制器配置。
- 通过代码直接访问 `ControllerRegistry` 单例对象。
新版控制器不再通过配置文件夹加载,只能通过此 API 注册。
## `register(id, src){:java}`
- 注册一个动作控制器,支持三种数据源
- **参数**:
- `id`: String — 控制器唯一标识
- `src`: YamlConfiguration / String / File — 控制器配置数据源
- **返回值**:无
- **调用示例**
```java
// 从文件注册
ControllerRegistry.INSTANCE.register("控制器ID", new File("文件路径"));
// 从YAML字符串注册
ControllerRegistry.INSTANCE.register("控制器ID", yamlString);
// 从YamlConfiguration注册
ControllerRegistry.INSTANCE.register("控制器ID", yamlConfig);
```
## `unregister(id){:java}`
- 注销一个动作控制器
- **参数**:`id`: String — 控制器唯一标识
- **返回值**:无
- **调用示例**
```java
ControllerRegistry.INSTANCE.unregister("combat");
```
## `syncPlayers(){:java}`
- 将所有已注册的控制器同步到所有在线玩家的客户端
- **参数**:无
- **返回值**:无
- **调用示例**
```java
ControllerRegistry.INSTANCE.syncPlayers();
```
注册或修改控制器后,需要调用 `syncPlayers()` 才能让在线玩家的客户端生效。
---
## ArcartXSoundPlayer:音效播放器
URL: https://wiki.arcartx.com/docs/server_api/12_sound_player
## ArcartXSoundPlayer
- 音效播放器提供了在世界中播放自定义音效的能力。
- 通过 `ArcartXAPI.getSoundPlayer()` 获取。
- 所有方法都是Kotlin扩展函数,在Java中作为静态方法调用。
## `World.playSoundForPlayer(player, location, resourcePath, soundCategory, distOrRoll, pitch, keepTime){:java}`
- 为指定玩家在指定位置播放音效,仅当玩家在同一世界且在传播距离内时才会播放
- **参数**:
- `player`: Player — 目标玩家
- `location`: Location — 音效播放位置
- `resourcePath`: String — 音效资源路径
- `soundCategory`: String — 音效类别(如 `master`、`music`、`ambient`)
- `distOrRoll`: int — 传播距离/衰减
- `pitch`: double — 音调
- `keepTime`: int — 持续时间(毫秒)
- **返回值**:无
- **调用示例**
```java
// Kotlin
world.playSoundForPlayer(player, location, "sounds/bell.ogg", "master", 32, 1.0, 5000)
// Java
ArcartXSoundPlayer.playSoundForPlayer(world, player, location, "sounds/bell.ogg",
"master", 32, 1.0, 5000);
```
## `World.playSoundOnWorld(location, resourcePath, soundCategory, distOrRoll, pitch, keepTime){:java}`
- 在世界指定位置播放音效,范围内所有玩家可听到
- **参数**:
- `location`: Location — 音效播放位置
- `resourcePath`: String — 音效资源路径
- `soundCategory`: String — 音效类别
- `distOrRoll`: int — 传播距离/衰减
- `pitch`: double — 音调
- `keepTime`: int — 持续时间(毫秒)
- **返回值**:无
- **调用示例**
```java
// Kotlin
world.playSoundOnWorld(location, "sounds/thunder.ogg", "ambient", 64, 1.0, 8000)
// Java
ArcartXSoundPlayer.playSoundOnWorld(world, location, "sounds/thunder.ogg",
"ambient", 64, 1.0, 8000);
```
---
## ArcartXNetworkSender:网络发送器
URL: https://wiki.arcartx.com/docs/server_api/13_network_sender
## ArcartXNetworkSender
- 网络发送器提供了更底层的网络数据包发送能力,所有方法都是**点对点**发送给指定玩家。
- 通过 `ArcartXAPI.getNetworkSender()` 获取。
- 大多数场景下你应该优先使用 `ArcartXPlayer` 或其他高级API,仅在需要精细控制时使用本类。
## 自定义数据包
### `sendCustomPacket(player, id, args...){:java}`
- 向玩家发送自定义数据包
- **参数**:
- `player`: Player — 目标玩家
- `id`: String — 数据包ID
- `args`: String... — 数据内容(可变参数)
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getNetworkSender().sendCustomPacket(player, "my_plugin:sync", "data1", "data2");
```
## 服务端变量
### `sendServerVariable(player, variableName, value){:java}`
- 向玩家客户端设置一个服务端变量,可在Shimmer脚本中读取
- **参数**:
- `player`: Player — 目标玩家
- `variableName`: String — 变量名
- `value`: Object — 变量值
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getNetworkSender().sendServerVariable(player, "player_level", 10);
```
### `sendMultipleServerVariable(player, variables){:java}`
- 批量设置服务端变量
- **参数**:
- `player`: Player — 目标玩家
- `variables`: Map<String, Object> — 变量映射
- **返回值**:无
- **调用示例**
```java
Map vars = new HashMap<>();
vars.put("hp", 100);
vars.put("mp", 50);
ArcartXAPI.getNetworkSender().sendMultipleServerVariable(player, vars);
```
### `removeServerVariable(player, variableName, startWith){:java}`
- 移除玩家客户端的服务端变量
- **参数**:
- `player`: Player — 目标玩家
- `variableName`: String — 变量名
- `startWith`: boolean — 是否匹配以该名称开头的所有变量(默认false)
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getNetworkSender().removeServerVariable(player, "player_", true);
```
## 伤害显示
### `sendDamageDisplay(player, configID, damage, location){:java}`
- 在指定位置为玩家显示伤害数字
- **参数**:
- `player`: Player — 目标玩家
- `configID`: String — 伤害显示配置ID
- `damage`: double — 伤害数值
- `location`: Location — 显示位置
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getNetworkSender().sendDamageDisplay(player, "critical", 999.0, location);
```
### `sendDamageDisplay(player, configID, damage, target){:java}`
- 在目标实体位置为玩家显示伤害数字
- **参数**:
- `player`: Player — 目标玩家
- `configID`: String — 伤害显示配置ID
- `damage`: double — 伤害数值
- `target`: Entity — 目标实体
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getNetworkSender().sendDamageDisplay(player, "default", 50.0, targetEntity);
```
## 图片资源
### `sendBase64Image(player, resourceID, base64){:java}`
- 向玩家客户端发送Base64编码的图片资源
- **参数**:
- `player`: Player — 目标玩家
- `resourceID`: String — 资源ID
- `base64`: String — Base64编码的图片数据
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getNetworkSender().sendBase64Image(player, "avatar", base64String);
```
## 音效控制
### `sendSoundPlay(player, name, path, x, y, z, soundCategory, distOrRoll, pitch, keepTime){:java}`
- 在指定坐标播放具名音效
- **参数**:
- `player`: Player — 目标玩家
- `name`: String — 音效名称(用于后续停止)
- `path`: String — 音效资源路径
- `x` `y` `z`: int — 播放坐标
- `soundCategory`: String — 音效类别(默认 `master`)
- `distOrRoll`: int — 传播距离(默认16)
- `pitch`: double — 音调(默认1.0)
- `keepTime`: int — 持续时间(默认5000毫秒)
- **返回值**:无
### `sendSoundPlay(player, name, path, entity, ...){:java}`
- 绑定实体播放具名音效(多个重载版本)
- 支持绑定到实体、绑定到自身、有名/无名等多种组合
- 具名音效可以通过 `sendStopSound` 停止播放
### `sendStopSound(player, name){:java}`
- 停止播放指定名称的音效
- **参数**:
- `player`: Player — 目标玩家
- `name`: String — 音效名称
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getNetworkSender().sendStopSound(player, "bgm");
```
## 实体控制
### `sendSetEntityModel(player, entity, modelID, scale){:java}`
- 为指定玩家设置某个实体的模型显示
- **参数**:
- `player`: Player — 目标玩家
- `entity`: UUID — 实体UUID
- `modelID`: String — 模型ID
- `scale`: double — 缩放比例(默认1.0)
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getNetworkSender().sendSetEntityModel(player, entityUUID, "custom_model", 1.5);
```
### `sendSetEntityAnimation(player, entity, animationName, speed, transitionTime, time){:java}`
- 为指定玩家播放某个实体的动画
- **参数**:
- `player`: Player — 目标玩家
- `entity`: UUID — 实体UUID
- `animationName`: String — 动画名称
- `speed`: double — 播放速度
- `transitionTime`: int — 过渡时间(毫秒)
- `time`: long — 持续时间(毫秒)
- **返回值**:无
### `sendSetEntitySize(player, entity, width, height){:java}`
- 为指定玩家设置某个实体的碰撞体积显示
- **参数**:
- `player`: Player — 目标玩家
- `entity`: UUID — 实体UUID
- `width`: double — 宽度
- `height`: double — 高度
- **返回值**:无
---
## ArcartXLinkManager:第三方桥接
URL: https://wiki.arcartx.com/docs/server_api/14_link_manager
## ArcartXLinkManager
- 第三方桥接管理器允许你为ArcartX注册自定义的属性系统、经济系统、物品系统和PlaceholderAPI变量。
- 通过代码直接访问 `ArcartXLinkManager` 单例对象。
## 属性系统
### `registerAttributeProvider(attributeProvider){:java}`
- 注册一个属性提供者
- **参数**:`attributeProvider`: AttributeProvider — 属性提供者实例
- **返回值**:无
- **调用示例**
```java
ArcartXLinkManager.INSTANCE.registerAttributeProvider(new MyAttributeProvider());
```
### `getAttributeProvider(name){:java}`
- 获取指定名称的属性提供者
- **参数**:`name`: String — 提供者标识
- **返回值**:`AttributeProvider?`
**AttributeProvider 接口**:
```java
public interface AttributeProvider {
String getIdentifier();
void addAttribute(LivingEntity entity, String sourceID, List list);
void addAttribute(LivingEntity entity, String sourceID, ItemStack itemStack);
void removeAttribute(LivingEntity entity, String sourceID);
}
```
## 经济系统
### `registerEconomyProvider(economyProvider){:java}`
- 注册一个经济提供者
- **参数**:`economyProvider`: EconomyProvider — 经济提供者实例
- **返回值**:无
- **调用示例**
```java
ArcartXLinkManager.INSTANCE.registerEconomyProvider(new MyEconomyProvider());
```
### `getEconomyProvider(name){:java}`
- 获取指定名称的经济提供者
- **参数**:`name`: String — 提供者标识
- **返回值**:`EconomyProvider?`
**EconomyProvider 接口**:
```java
public interface EconomyProvider {
String getIdentifier();
String getDisplayName();
boolean addEconomy(Player player, double amount);
double getEconomy(Player player);
boolean takeEconomy(Player player, double amount);
}
```
## 物品系统
### `registerItemProvider(itemProvider){:java}`
- 注册一个物品提供者
- **参数**:`itemProvider`: ItemProvider — 物品提供者实例
- **返回值**:无
- **调用示例**
```java
ArcartXLinkManager.INSTANCE.registerItemProvider(new MyItemProvider());
```
### `getItemProvider(name){:java}`
- 获取指定名称的物品提供者
- **参数**:`name`: String — 提供者标识
- **返回值**:`ItemProvider?`
**ItemProvider 接口**:
```java
public interface ItemProvider {
String getIdentifier();
ItemStack generateItemStack(String id);
}
```
## PlaceholderAPI
### `registerPlaceholder(placeholder){:java}`
- 注册一个ArcartX PlaceholderAPI变量
- **参数**:`placeholder`: AXPlaceholder — 变量实例
- **返回值**:无
- **调用示例**
```java
ArcartXLinkManager.INSTANCE.registerPlaceholder(new MyPlaceholder());
```
需要服务端安装PlaceholderAPI插件才能使用此功能。
### `unRegisterPlaceholder(placeholder){:java}`
- 注销一个PlaceholderAPI变量
- **参数**:`placeholder`: AXPlaceholder — 变量实例
- **返回值**:无
**AXPlaceholder 抽象类**:
- 继承此类并使用 `@Placeholder` 注解标记方法即可注册变量
- 方法参数为 `PlaceholderContext`,返回值为 `String`
- 使用 `@PlaceholderArgs` 注解声明参数
```java
public class MyPlaceholder extends AXPlaceholder {
@Override
public String getIdentifier() {
return "myplugin";
}
@Placeholder("level")
public String getLevel(PlaceholderContext context) {
// %arcartx_myplugin_level%
return String.valueOf(getPlayerLevel(context.getPlayer()));
}
@Placeholder("stat")
@PlaceholderArgs({"statName"})
public String getStat(PlaceholderContext context) {
// %arcartx_myplugin_stat_%
String statName = context.getArg(0);
return getStatValue(context.getPlayer(), statName);
}
}
```
---
## ItemStackUtils:物品工具
URL: https://wiki.arcartx.com/docs/server_api/16_itemstack_utils
## ItemStackUtils
- 物品工具集提供了一系列 `ItemStack` 的Kotlin扩展函数,用于便捷地操作物品的Lore、名称、NBT标签以及ArcartX专属属性。
- 位于 `priv.seventeen.artist.arcartx.util.ItemStackUtils`,所有方法均为静态方法。
- 在Kotlin中可直接作为扩展函数调用,在Java中通过 `ItemStackUtils.xxx(itemStack, ...)` 调用。
## Lore操作
### `ItemStack.addLore(text){:java}`
- 为物品追加一行Lore
- **参数**:`text`: String — Lore文本,支持 `&` 颜色代码(会自动转换为 `§`)
- **返回值**:无
- **调用示例**
```java
// Kotlin
itemStack.addLore("&a这是一行绿色Lore")
// Java
ItemStackUtils.addLore(itemStack, "&a这是一行绿色Lore");
```
### `ItemStack.setLore(text, line){:java}`
- 设置物品指定行的Lore
- **参数**:
- `text`: String — Lore文本
- `line`: int — 行号(从0开始)
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.setLore(itemStack, "&b新内容", 0);
```
### `ItemStack.insertLore(text, line){:java}`
- 在物品指定行插入一行Lore,原有内容向下移动
- **参数**:
- `text`: String — Lore文本
- `line`: int — 插入位置行号
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.insertLore(itemStack, "&e插入的内容", 2);
```
### `ItemStack.removeLore(line){:java}`
- 删除物品指定行的Lore
- **参数**:`line`: int — 要删除的行号
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.removeLore(itemStack, 0);
```
### `ItemStack.containsLore(text){:java}`
- 判断物品Lore中是否包含指定文本(模糊匹配)
- **参数**:`text`: String — 要搜索的文本
- **返回值**:boolean
- **调用示例**
```java
boolean has = ItemStackUtils.containsLore(itemStack, "稀有");
```
## 名称操作
### `ItemStack.setDisplayName(name){:java}`
- 设置物品的显示名称
- **参数**:`name`: String — 显示名称,支持 `&` 颜色代码
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.setDisplayName(itemStack, "&6传说之剑");
```
## ArcartX专属属性
### `ItemStack.setIcon(path){:java}`
- 设置物品的图标贴图路径(ArcartX客户端渲染)
- **参数**:`path`: String — 图标资源路径
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.setIcon(itemStack, "icons/sword.png");
```
### `ItemStack.setModel(path){:java}`
- 设置物品的3D模型ID
- **参数**:`path`: String — 模型ID
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.setModel(itemStack, "my_sword");
```
### `ItemStack.setFPModel(path){:java}`
- 设置物品的第一人称模型ID
- **参数**:`path`: String — 第一人称模型ID
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.setFPModel(itemStack, "my_sword_fp");
```
### `ItemStack.addExtraModel(locatorName, modelID){:java}`
- 为物品添加额外渲染模型,挂载在指定定位器上
- **参数**:
- `locatorName`: String — 定位器名称
- `modelID`: String — 模型ID
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.addExtraModel(itemStack, "blade_extra", "glow_effect");
```
### `ItemStack.setUrl(path){:java}`
- 设置物品在UI界面中显示的贴图路径
- **参数**:`path`: String — 贴图资源路径
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.setUrl(itemStack, "ui/items/sword.png");
```
### `ItemStack.setDrop(path){:java}`
- 设置物品掉落时的附加模型
- **参数**:`path`: String — 掉落模型ID
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.setDrop(itemStack, "drop_sword");
```
## 冷却系统
### `ItemStack.setCoolDownTag(value){:java}`
- 设置物品的冷却标签,相同标签的物品共享冷却
- **参数**:`value`: String — 冷却标签
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.setCoolDownTag(itemStack, "skill_group_1");
```
### `ItemStack.getCooldownTag(){:java}`
- 获取物品的冷却标签
- **参数**:无
- **返回值**:String — 冷却标签,无标签时返回空字符串
- **调用示例**
```java
String tag = ItemStackUtils.getCooldownTag(itemStack);
```
### `ItemStack.getCooldown(player){:java}`
- 获取物品对于指定玩家的剩余冷却时间
- **参数**:`player`: Player — 玩家
- **返回值**:long — 剩余冷却时间(毫秒),0表示已就绪
- **调用示例**
```java
long remaining = ItemStackUtils.getCooldown(itemStack, player);
```
### `ItemStack.setCooldown(player, time){:java}`
- 为物品设置对于指定玩家的冷却时间
- **参数**:
- `player`: Player — 玩家
- `time`: long — 冷却时间(毫秒)
- **返回值**:无
- **调用示例**
```java
ItemStackUtils.setCooldown(itemStack, player, 3000); // 3秒冷却
```
## NBT操作
### `ItemStack.getTag(key){:java}`
- 获取物品的NBT标签值,支持 `.` 分隔的深层路径
- **参数**:`key`: String — NBT键名,支持 `a.b.c` 格式的深层路径
- **返回值**:String — 标签值,不存在时返回空字符串
- **调用示例**
```java
String value = ItemStackUtils.getTag(itemStack, "custom.level");
```
---
## PlayerUtils:玩家工具
URL: https://wiki.arcartx.com/docs/server_api/17_player_utils
## PlayerUtils
- 玩家工具集提供了 `Player` 的Kotlin扩展函数和扩展属性。
- 位于 `priv.seventeen.artist.arcartx.util.PlayerUtils`。
## `Player.isNpc(){:java}`
- 判断玩家是否为NPC(通过检查是否有 `NPC` Metadata)
- **参数**:无
- **返回值**:boolean
- **调用示例**
```java
// Kotlin
if (player.isNpc()) return
// Java
if (PlayerUtils.isNpc(player)) return;
```
## `Player.arcartXHandler{:java}`
- 获取玩家对应的 `ArcartXPlayer` 管理对象(扩展属性)
- **返回值**:`ArcartXPlayer?` — 可能为null
- **调用示例**
```java
// Kotlin
player.arcartXHandler?.setModel("knight", 1.0)
// Java
ArcartXPlayer handler = PlayerUtils.getArcartXHandler(player);
if (handler != null) {
handler.setModel("knight", 1.0);
}
```
这是 `ArcartXAPI.getEntityManager().getPlayer(player)` 的快捷方式,功能完全相同。
## `Player.dispatchOpCommand(command){:java}`
- 以OP权限执行一条指令
- **参数**:`command`: String — 指令内容(不含 `/`)
- **返回值**:无
- **调用示例**
```java
// Kotlin
player.dispatchOpCommand("give ${player.name} diamond 1")
// Java
PlayerUtils.dispatchOpCommand(player, "give " + player.getName() + " diamond 1");
```
---
## EntityUtils:实体工具
URL: https://wiki.arcartx.com/docs/server_api/18_entity_utils
## EntityUtils
- 实体工具集提供了 `Entity` 的Kotlin扩展函数和扩展属性。
- 位于 `priv.seventeen.artist.arcartx.util.EntityUtils`。
## `Entity.setSize(width, height){:java}`
- 设置实体的碰撞体积(通过NMS直接修改)
- **参数**:
- `width`: float — 碰撞箱宽度
- `height`: float — 碰撞箱高度
- **返回值**:无
- **调用示例**
```java
// Kotlin
entity.setSize(2.0f, 3.0f)
// Java
EntityUtils.setSize(entity, 2.0f, 3.0f);
```
此方法仅修改服务端碰撞体积,不会同步到客户端显示。如果需要同时同步客户端,请使用 `ArcartXEntity.setSize()`。
## `Entity.doWithSeenBy(action){:java}`
- 对所有能看到该实体的玩家执行操作,如果实体本身是玩家也会包含自身
- **参数**:`action`: PlayerCallBack — 对每个玩家执行的回调
- **返回值**:无
- **调用示例**
```java
// Kotlin
entity.doWithSeenBy { player ->
// 对每个能看到该实体的玩家执行操作
}
// Java
EntityUtils.doWithSeenBy(entity, player -> {
// 对每个能看到该实体的玩家执行操作
});
```
## `Entity.arcartXHandler{:java}`
- 获取实体对应的 `ArcartXEntity` 管理对象(扩展属性)
- **返回值**:`ArcartXEntity?` — 可能为null(仅返回已缓存的实体对象)
- **调用示例**
```java
// Kotlin
entity.arcartXHandler?.playAnimation("attack", 1.0, 5, -1)
// Java
ArcartXEntity handler = EntityUtils.getArcartXHandler(entity);
```
## `Entity.isProxy{:java}`
- 判断实体是否为MythicMobs Hitbox代理实体(扩展属性)
- **返回值**:boolean
- **调用示例**
```java
// Kotlin
if (entity.isProxy) return
// Java
if (EntityUtils.isProxy(entity)) return;
```
---
## SchedulerUtils:调度工具
URL: https://wiki.arcartx.com/docs/server_api/19_scheduler_utils
## SchedulerUtils
- 调度工具集提供了 `Plugin` 的Kotlin扩展函数,简化Bukkit调度器的使用。
- 位于 `priv.seventeen.artist.arcartx.util.SchedulerUtils`。
## `Plugin.run(runnable){:java}`
- 在主线程执行任务
- **参数**:`runnable`: Runnable — 要执行的任务
- **返回值**:无
- **调用示例**
```java
// Kotlin
plugin.run { player.sendMessage("Hello") }
// Java
SchedulerUtils.run(plugin, () -> player.sendMessage("Hello"));
```
## `Plugin.runAsync(runnable){:java}`
- 在异步线程执行任务
- **参数**:`runnable`: Runnable — 要执行的任务
- **返回值**:无
- **调用示例**
```java
SchedulerUtils.runAsync(plugin, () -> {
// 异步操作,如数据库查询
});
```
## `Plugin.runLater(runnable, tick){:java}`
- 在主线程延迟执行任务
- **参数**:
- `runnable`: Runnable — 要执行的任务
- `tick`: int — 延迟tick数(20tick = 1秒)
- **返回值**:无
- **调用示例**
```java
SchedulerUtils.runLater(plugin, () -> {
// 1秒后执行
}, 20);
```
## `Plugin.runLaterAsync(runnable, tick){:java}`
- 在异步线程延迟执行任务
- **参数**:
- `runnable`: Runnable — 要执行的任务
- `tick`: int — 延迟tick数
- **返回值**:无
- **调用示例**
```java
SchedulerUtils.runLaterAsync(plugin, () -> {
// 异步延迟执行
}, 40);
```
## `Plugin.ensureMainThread(runnable){:java}`
- 确保任务在主线程执行。如果当前已在主线程则直接执行,否则调度到主线程
- **参数**:`runnable`: Runnable — 要执行的任务
- **返回值**:无
- **调用示例**
```java
SchedulerUtils.ensureMainThread(plugin, () -> {
// 保证在主线程执行,适合操作Bukkit API
entity.teleport(location);
});
```
## `Plugin.ensureAsyncThread(runnable){:java}`
- 确保任务在异步线程执行。如果当前已在异步线程则直接执行,否则调度到异步线程
- **参数**:`runnable`: Runnable — 要执行的任务
- **返回值**:无
- **调用示例**
```java
SchedulerUtils.ensureAsyncThread(plugin, () -> {
// 保证在异步线程执行,适合IO操作
saveToDatabase();
});
```
---
## ArcartXAPI:API入口
URL: https://wiki.arcartx.com/docs/server_api/1_api_entry
## ArcartXAPI
- `ArcartXAPI` 是ArcartX所有服务端API的统一入口,位于 `priv.seventeen.artist.arcartx.api` 包下。
- 它是一个单例对象,所有方法均为静态方法,可直接调用。
## `getUIRegistry(){:java}`
- 获取UI注册管理器
- **参数**:无
- **返回值**:`ArcartXUIRegistry`
- **调用示例**
```java
ArcartXUIRegistry registry = ArcartXAPI.getUIRegistry();
```
## `getKeyBindRegistry(){:java}`
- 获取按键绑定注册管理器
- **参数**:无
- **返回值**:`ArcartXKeyBindRegistry`
- **调用示例**
```java
ArcartXKeyBindRegistry registry = ArcartXAPI.getKeyBindRegistry();
```
## `getEntityManager(){:java}`
- 获取实体管理器
- **参数**:无
- **返回值**:`ArcartXEntityManager`
- **调用示例**
```java
ArcartXEntityManager manager = ArcartXAPI.getEntityManager();
```
## `getSoundPlayer(){:java}`
- 获取音效播放器
- **参数**:无
- **返回值**:`ArcartXSoundPlayer`
- **调用示例**
```java
ArcartXSoundPlayer player = ArcartXAPI.getSoundPlayer();
```
## `getNetworkSender(){:java}`
- 获取网络发送器
- **参数**:无
- **返回值**:`ArcartXNetworkSender`
- **调用示例**
```java
ArcartXNetworkSender sender = ArcartXAPI.getNetworkSender();
```
## `getAreaManager(){:java}`
- 获取区域管理器
- **参数**:无
- **返回值**:`ArcartXAreaManager`
- **调用示例**
```java
ArcartXAreaManager manager = ArcartXAPI.getAreaManager();
```
## `getEffectManager(){:java}`
- 获取特效管理器
- **参数**:无
- **返回值**:`ArcartXEffectManager`
- **调用示例**
```java
ArcartXEffectManager manager = ArcartXAPI.getEffectManager();
```
---
## ChatUtils:聊天工具
URL: https://wiki.arcartx.com/docs/server_api/20_chat_utils
## ChatUtils
- 聊天工具集提供了字符串的颜色代码处理。
- 位于 `priv.seventeen.artist.arcartx.util.ChatUtils`。
## `String.replaceColorChar(){:java}`
- 将字符串中的 `&` 颜色代码替换为 Minecraft 的 `§` 颜色代码
- **参数**:无(扩展函数,作用于字符串自身)
- **返回值**:String — 替换后的字符串
- **调用示例**
```java
// Kotlin
val colored = "&a绿色文本&b蓝色文本".replaceColorChar()
// 结果: "§a绿色文本§b蓝色文本"
// Java
String colored = ChatUtils.replaceColorChar("&a绿色文本&b蓝色文本");
```
---
## JsonUtils:JSON工具
URL: https://wiki.arcartx.com/docs/server_api/21_json_utils
## JsonUtils
- JSON工具集基于Gson,提供了对象与JSON字符串之间的快捷转换。
- 位于 `priv.seventeen.artist.arcartx.util.JsonUtils`。
## `Any.toJson(){:java}`
- 将任意对象序列化为JSON字符串
- **参数**:无(扩展函数,作用于对象自身)
- **返回值**:String — JSON字符串
- **调用示例**
```java
// Kotlin
val json = myObject.toJson()
// Java
String json = JsonUtils.toJson(myObject);
```
## `String.fromJson(clazz){:java}`
- 将JSON字符串反序列化为指定类型的对象
- **参数**:`clazz`: Class<T> — 目标类型
- **返回值**:T — 反序列化后的对象
- **调用示例**
```java
// Kotlin
val obj = jsonString.fromJson(MyData::class.java)
// Java
MyData obj = JsonUtils.fromJson(jsonString, MyData.class);
```
---
## 回调接口
URL: https://wiki.arcartx.com/docs/server_api/22_callbacks
## 回调接口
- ArcartX定义了一组函数式接口用于各种回调场景,位于 `priv.seventeen.artist.arcartx.util.collections` 包下。
- 所有接口均为函数式接口(`fun interface`),在Java中可以使用Lambda表达式。
## `CallBack`
- 最基础的无参回调接口
```java
@FunctionalInterface
public interface CallBack {
void call();
}
```
- **使用场景**:UI打开回调等不需要参数的场景
- **调用示例**
```java
registry.open(player, "my_ui", () -> {
// UI打开后执行
});
```
## `PlayerCallBack`
- 接收一个 `Player` 参数的回调接口
```java
@FunctionalInterface
public interface PlayerCallBack {
void call(Player player);
}
```
- **使用场景**:按键绑定的按下/释放回调、实体可见性遍历等
- **调用示例**
```java
entity.doWithSeenBy(player -> {
player.sendMessage("你看到了这个实体");
});
```
## `KeyCallBack`
- 按键回调接口,包含按下和释放两个方法
```java
public interface KeyCallBack {
default void onPress(Player player) {}
default void onRelease(Player player) {}
}
```
- **使用场景**:注册按键绑定时的回调
- **调用示例**
```java
registry.registerClientKeyBind("my_key", "我的插件", "G", new KeyCallBack() {
@Override
public void onPress(Player player) {
// 按下
}
@Override
public void onRelease(Player player) {
// 释放
}
});
```
`KeyCallBack` 不是函数式接口(有两个方法),在Java中需要使用匿名类实现。
## `UICallBack`
- UI事件回调接口,接收一个 `CallData` 参数
```java
@FunctionalInterface
public interface UICallBack {
void call(CallData event);
}
```
- **使用场景**:UI的打开、关闭、数据包回调
## `CallData`
- UI回调的数据载体
```java
public record CallData(Player player, String identifier, List data) {}
```
- `player` — 触发事件的玩家
- `identifier` — 事件标识(如数据包处理器名称)
- `data` — 数据内容列表
---
## ArcartXEntityManager:实体管理器
URL: https://wiki.arcartx.com/docs/server_api/2_entity_manager
## ArcartXEntityManager
- 实体管理器负责管理所有 ArcartX 实体对象和玩家对象的生命周期。
- 通过 `ArcartXAPI.getEntityManager()` 获取。
- 实体缓存会按照配置的间隔自动清理已失效的实体,无需手动管理。
## `getPlayer(player){:java}`
- 获取玩家对应的ArcartX玩家管理对象,如果玩家是NPC则返回null
- **参数**:`player`: Player — Bukkit玩家对象
- **返回值**:`ArcartXPlayer?` — 玩家管理对象,可能为null
- **调用示例**
```java
ArcartXPlayer axPlayer = ArcartXAPI.getEntityManager().getPlayer(player);
```
## `removePlayer(player){:java}`
- 移除玩家的ArcartX管理对象,同时会清除该玩家在其他玩家客户端上的控制器设置
- **参数**:`player`: Player — Bukkit玩家对象
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getEntityManager().removePlayer(player);
```
通常您不需要手动调用此方法,ArcartX会在玩家退出时自动处理。
## `getOrCreateEntity(entity){:java}`
- 获取或创建实体对应的ArcartX实体对象。如果传入的是玩家(非NPC),会自动返回ArcartXPlayer对象
- **参数**:`entity`: Entity — Bukkit实体对象
- **返回值**:`ArcartXEntity?` — 实体管理对象,可能为null
- **调用示例**
```java
ArcartXEntity axEntity = ArcartXAPI.getEntityManager().getOrCreateEntity(entity);
```
## `getEntity(uuid){:java}`
- 通过UUID获取已缓存的ArcartX实体对象,会优先查找玩家缓存
- **参数**:`uuid`: UUID — 实体UUID
- **返回值**:`ArcartXEntity?` — 实体管理对象,可能为null
- **调用示例**
```java
ArcartXEntity axEntity = ArcartXAPI.getEntityManager().getEntity(uuid);
```
## `removeEntity(entity){:java}`
- 移除实体的ArcartX管理对象。如果传入的是玩家则不会执行任何操作
- **参数**:`entity`: Entity — Bukkit实体对象
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getEntityManager().removeEntity(entity);
```
---
## ArcartXEntity:实体对象
URL: https://wiki.arcartx.com/docs/server_api/3_arcartx_entity
## ArcartXEntity
- `ArcartXEntity` 是ArcartX对Bukkit实体的包装对象,提供了模型、动画、发光、音效等功能的控制接口。
- 通过 `ArcartXEntityManager.getOrCreateEntity(entity)` 获取。
- `ArcartXPlayer` 继承自此类,玩家对象拥有本页所有方法以及更多扩展功能。
- 本类所有涉及客户端显示的方法均为**范围广播**模式——会向所有能看到该实体的玩家发送数据包。
## 模型管理
### `setModel(modelID, scale){:java}`
- 为实体设置模型
- **参数**:
- `modelID`: String — 模型ID
- `scale`: double — 模型缩放比例
- **返回值**:无
- **调用示例**
```java
axEntity.setModel("my_model", 1.0);
```
### `setModel(modelID, scale, reset){:java}`
- 为实体设置模型,可选择是否重置动画状态
- **参数**:
- `modelID`: String — 模型ID
- `scale`: double — 模型缩放比例
- `reset`: boolean — 是否重置动画状态
- **返回值**:无
- **调用示例**
```java
axEntity.setModel("my_model", 1.5, true);
```
### `removeModel(){:java}`
- 移除实体的模型
- **参数**:无
- **返回值**:无
- **调用示例**
```java
axEntity.removeModel();
```
## 碰撞与体积
### `setSize(width, height){:java}`
- 设置实体的碰撞体积,同时会同步到客户端显示
- **参数**:
- `width`: double — 碰撞箱宽度
- `height`: double — 碰撞箱高度
- **返回值**:无
- **调用示例**
```java
axEntity.setSize(0.6, 1.8);
```
此方法会在主线程执行,如果你在异步线程调用,它会自动切换到主线程。
### `setHideHitBox(hide){:java}`
- 设置是否隐藏实体的碰撞箱显示
- **参数**:`hide`: boolean — 是否隐藏
- **返回值**:无
- **调用示例**
```java
axEntity.setHideHitBox(true);
```
## 骨骼与动画
### `setHideBone(bone, hide){:java}`
- 隐藏或显示模型的指定骨骼
- **参数**:
- `bone`: String — 骨骼名称
- `hide`: boolean — 是否隐藏
- **返回值**:无
- **调用示例**
```java
axEntity.setHideBone("head", true);
```
### `setDefaultState(state, name){:java}`
- 设置实体模型的默认动画状态
- **参数**:
- `state`: String — 状态名称
- `name`: String — 动画名称
- **返回值**:无
- **调用示例**
```java
axEntity.setDefaultState("idle", "idle_animation");
```
### `playAnimation(animation, speed, transitionTime, keepTime){:java}`
- 为实体播放一次动画
- **参数**:
- `animation`: String — 动画名称
- `speed`: double — 播放速度
- `transitionTime`: int — 过渡时间(毫秒)
- `keepTime`: long — 持续时间(毫秒),-1为播放完整动画
- **返回值**:无
- **调用示例**
```java
axEntity.playAnimation("attack", 1.0, 5, -1);
```
## 显示效果
### `setDisplayName(displayName){:java}`
- 设置是否显示实体名称
- **参数**:`displayName`: boolean — 是否显示
- **返回值**:无
- **调用示例**
```java
axEntity.setDisplayName(false);
```
### `setGlowColor(r, g, b){:java}`
- 设置实体的发光颜色
- **参数**:
- `r`: int — 红色分量(0-255)
- `g`: int — 绿色分量(0-255)
- `b`: int — 蓝色分量(0-255)
- **返回值**:无
- **调用示例**
```java
axEntity.setGlowColor(255, 0, 0); // 红色发光
```
### `enableGlow(){:java}`
- 启用实体发光效果
- **参数**:无
- **返回值**:无
- **调用示例**
```java
axEntity.enableGlow();
```
### `disableGlow(){:java}`
- 关闭实体发光效果
- **参数**:无
- **返回值**:无
- **调用示例**
```java
axEntity.disableGlow();
```
## 音效
### `playSound(resourcePath, soundCategory, distOrRoll, pitch, keepTime){:java}`
- 为实体播放音效,音效会跟随实体移动,向所有能看到该实体的玩家广播
- **参数**:
- `resourcePath`: String — 音效资源路径
- `soundCategory`: String — 音效类别(如 `master`、`music`)
- `distOrRoll`: int — 传播距离/衰减
- `pitch`: double — 音调
- `keepTime`: int — 持续时间(毫秒)
- **返回值**:无
- **调用示例**
```java
axEntity.playSound("sounds/hit.ogg", "master", 16, 1.0, 3000);
```
## 伤害显示
### `broadcastDamageDisplay(damageDisplayConfigId, damage){:java}`
- 在实体位置广播伤害数字,所有能看到该实体的玩家都会看到
- **参数**:
- `damageDisplayConfigId`: String — 伤害显示配置ID
- `damage`: double — 伤害数值
- **返回值**:无
- **调用示例**
```java
axEntity.broadcastDamageDisplay("default", 100.0);
```
此方法是**范围广播**模式,会向所有能看到该实体的玩家发送伤害数字。如果你只想让特定玩家看到伤害数字,请使用 `sendDamageDisplayToPlayers` 或 `ArcartXPlayer.addDamageDisplay`。
### `sendDamageDisplayToPlayers(damageDisplayConfigId, damage, players){:java}`
- 在实体位置显示伤害数字,仅指定列表中的玩家可见
- **参数**:
- `damageDisplayConfigId`: String — 伤害显示配置ID
- `damage`: double — 伤害数值
- `players`: List<Player> — 可见玩家列表
- **返回值**:无
- **调用示例**
```java
List viewers = Arrays.asList(player1, player2);
axEntity.sendDamageDisplayToPlayers("default", 50.0, viewers);
```
---
## ArcartXPlayer:玩家管理对象
URL: https://wiki.arcartx.com/docs/server_api/4_arcartx_player
## ArcartXPlayer
- `ArcartXPlayer` 继承自 `ArcartXEntity`,是ArcartX对玩家的完整管理对象。
- 通过 `ArcartXAPI.getEntityManager().getPlayer(player)` 获取。
- 除了继承自 `ArcartXEntity` 的所有方法外,还提供了大量玩家专属功能。
- 本类的方法分为两种发送模式:
- **点对点** — 仅向该玩家自身的客户端发送数据包(如相机、着色器、特效等)
- **广播** — 向所有能看到该玩家的客户端发送数据包(如模型、控制器、状态、额外模型、覆盖模型等)
模型管理、动画控制(setState / setController)、额外模型、覆盖模型等方法是**广播模式**,会同步给所有能看到该玩家的客户端。相机、着色器、天空盒、特效等方法是**点对点模式**,仅发送给该玩家自身。
## 模型管理
### `setModel(modelID, scale){:java}`
- 设置玩家模型,会触发 `PlayerModelUpdateEvent` 事件,并向所有能看到该玩家的其他玩家广播模型变更
- **参数**:
- `modelID`: String — 模型ID
- `scale`: double — 模型缩放比例
- **返回值**:无
- **调用示例**
```java
axPlayer.setModel("knight", 1.0);
```
### `removeModel(){:java}`
- 移除玩家模型,恢复默认外观
- **参数**:无
- **返回值**:无
- **调用示例**
```java
axPlayer.removeModel();
```
### `addExtraModel(locator, modelID){:java}`
- 为玩家添加额外模型,挂载在指定定位器上
- **参数**:
- `locator`: String — 定位器名称
- `modelID`: String — 模型ID
- **返回值**:无
- **调用示例**
```java
axPlayer.addExtraModel("back_extra", "wings_model");
```
### `removeExtraModel(locator){:java}`
- 移除玩家指定定位器上的额外模型
- **参数**:`locator`: String — 定位器名称
- **返回值**:无
- **调用示例**
```java
axPlayer.removeExtraModel("back_extra");
```
### `clearExtraModels(){:java}`
- 清除玩家所有额外模型
- **参数**:无
- **返回值**:无
- **调用示例**
```java
axPlayer.clearExtraModels();
```
## 动画控制
### `playFirstPersonAnimationByTime(animation, speed, keepTime){:java}`
- 为玩家播放第一人称动画,按持续时间控制
- **参数**:
- `animation`: String — 动画名称
- `speed`: double — 播放速度
- `keepTime`: int — 持续时间(毫秒)
- **返回值**:无
- **调用示例**
```java
axPlayer.playFirstPersonAnimationByTime("slash", 1.0, 500);
```
### `playFirstPersonAnimationByCountOf(animation, speed, count){:java}`
- 为玩家播放第一人称动画,按播放次数控制
- **参数**:
- `animation`: String — 动画名称
- `speed`: double — 播放速度
- `count`: int — 播放次数
- **返回值**:无
- **调用示例**
```java
axPlayer.playFirstPersonAnimationByCountOf("swing", 1.5, 3);
```
### `setState(controller, state){:java}`
- 设置玩家动作控制器的状态
- **参数**:
- `controller`: String — 控制器名称
- `state`: String — 状态名称
- **返回值**:无
- **调用示例**
```java
axPlayer.setState("combat", "attack_1");
```
### `setState(controller, state, speed){:java}`
- 设置玩家动作控制器的状态,指定播放速度
- **参数**:
- `controller`: String — 控制器名称
- `state`: String — 状态名称
- `speed`: double — 播放速度
- **返回值**:无
- **调用示例**
```java
axPlayer.setState("combat", "attack_1", 2.0);
```
### `setState(controller, state, speed, moveBreak){:java}`
- 设置玩家动作控制器的状态,指定播放速度和移动打断时间
- **参数**:
- `controller`: String — 控制器名称
- `state`: String — 状态名称
- `speed`: double — 播放速度
- `moveBreak`: long — 移动打断时间(毫秒),-1为不打断
- **返回值**:无
- **调用示例**
```java
axPlayer.setState("combat", "heavy_attack", 1.0, 2000);
```
### `setController(controller){:java}`
- 为玩家设置动作控制器
- **参数**:`controller`: String — 控制器配置ID
- **返回值**:无
- **调用示例**
```java
axPlayer.setController("combat_controller");
```
## 相机控制
### `setThirdPerson(enable){:java}`
- 将玩家设置为第三人称视角
- **参数**:`enable`: boolean — true 设置为第三人称 false 设置为第一人称
- **返回值**:无
- **调用示例**
```java
axPlayer.setThirdPerson(true);
```
### `setViewLockMode(mode){:java}`
- 设置视角锁定模式
- **参数**:`mode`: int — 锁定模式(0-关闭,1-强制锁定第一人称,2-强制锁定第三人称)
- **返回值**:无
- **调用示例**
```java
axPlayer.setViewLockMode(2);
```
### `setCameraFromPreset(id){:java}`
- 从预设配置设置玩家相机
- **参数**:`id`: String — 相机预设配置ID
- **返回值**:无
- **调用示例**
```java
axPlayer.setCameraFromPreset("idle");
```
### `setCameraLocation(offsetX, offsetY, offsetZ, freeView){:java}`
- 设置玩家相机的偏移位置
- **参数**:
- `offsetX`: double — X轴偏移
- `offsetY`: double — Y轴偏移
- `offsetZ`: double — Z轴偏移
- `freeView`: boolean — 是否允许自由视角
- **返回值**:无
- **调用示例**
```java
axPlayer.setCameraLocation(0, 2.0, -5.0, true);
```
### `startSceneCamera(sceneId){:java}`
- 开始播放场景相机
- **参数**:`sceneId`: String — 场景相机配置ID
- **返回值**:无
- **调用示例**
```java
axPlayer.startSceneCamera("intro_scene");
```
### `stopSceneCamera(){:java}`
- 停止场景相机播放
- **参数**:无
- **返回值**:无
- **调用示例**
```java
axPlayer.stopSceneCamera();
```
## 着色器与天空盒
### `enableShader(shader){:java}`
- 为玩家启用后处理着色器
- **参数**:`shader`: String — 着色器名称
- **返回值**:无
- **调用示例**
```java
axPlayer.enableShader("blur");
```
### `disableShader(){:java}`
- 关闭玩家的着色器效果
- **参数**:无
- **返回值**:无
- **调用示例**
```java
axPlayer.disableShader();
```
### `setSkyTexture(texturePath, forceNoCloud){:java}`
- 为玩家设置自定义天空盒贴图
- **参数**:
- `texturePath`: String — 天空盒贴图资源路径
- `forceNoCloud`: boolean — 是否强制隐藏云层
- **返回值**:无
- **调用示例**
```java
axPlayer.setSkyTexture("sky/night.png", true);
```
### `clearSkyTexture(){:java}`
- 清除玩家的自定义天空盒,恢复默认天空
- **参数**:无
- **返回值**:无
- **调用示例**
```java
axPlayer.clearSkyTexture();
```
### `setClientTitle(text){:java}`
- 设置玩家客户端的标题文本
- **参数**:`text`: String — 标题文本
- **返回值**:无
- **调用示例**
```java
axPlayer.setClientTitle("欢迎来到冒险世界");
```
## 特效
以下特效方法均为**点对点发送**,仅发送给该玩家自身的客户端。如果你需要让周围所有玩家都看到特效,请使用 `ArcartXEffectManager` 的范围广播方法。
### `spawnBedrockParticle(identifier, particleID, effectPosition){:java}`
- 在玩家客户端生成基岩粒子效果
- **参数**:
- `identifier`: String — 粒子标识符
- `particleID`: String — 粒子ID
- `effectPosition`: EffectPosition — 特效位置
- **返回值**:无
- **调用示例**
```java
axPlayer.spawnBedrockParticle("my_particle", "flame",
EffectPosition.followEntity(player));
```
**与 ArcartXEffectManager.spawnBedrockParticle 的区别**:
- `ArcartXPlayer.spawnBedrockParticle` — **点对点**,仅该玩家自身可见
- `ArcartXEffectManager.Entity.spawnBedrockParticle` — **范围广播**,所有能看到该实体的玩家可见
- `ArcartXEffectManager.World.spawnBedrockParticle` — **范围广播**,指定位置128格内所有玩家可见
选择哪个取决于你的需求:如果粒子只需要一个玩家看到,用Player版本;如果需要所有人看到(如技能特效),用EffectManager版本。
### `addWorldTexture(id, builder, effectPosition){:java}`
- 在玩家客户端添加世界贴图
- **参数**:
- `id`: String — 贴图唯一标识
- `builder`: WorldTextureBuilder — 贴图构建器
- `effectPosition`: EffectPosition — 特效位置
- **返回值**:无
- **调用示例**
```java
WorldTextureBuilder builder = new WorldTextureBuilder()
.setTexture("effects/magic_circle.png", true, true)
.setSize(256.0, 256.0)
.setLifeTime(-1);
axPlayer.addWorldTexture("magic_circle", builder,
EffectPosition.followEntity(player, 0, 0, 0, 0, 0, 0, true, true));
```
**与 ArcartXEffectManager.spawnWorldTextureEffect 的区别**:
- `ArcartXPlayer.addWorldTexture` — **点对点**,仅该玩家自身可见
- `ArcartXEffectManager.spawnWorldTextureEffect` — **范围广播**,周围所有玩家可见
### `removeWorldTexture(id){:java}`
- 移除玩家客户端的世界贴图
- **参数**:`id`: String — 贴图唯一标识
- **返回值**:无
- **调用示例**
```java
axPlayer.removeWorldTexture("magic_circle");
```
### `playBlockAnimation(x, y, z, animation, speed, transitionTime, keepTime){:java}`
- 在玩家客户端播放方块动画
- **参数**:
- `x` `y` `z`: int — 方块坐标
- `animation`: String — 动画名称
- `speed`: double — 播放速度
- `transitionTime`: int — 过渡时间(毫秒)
- `keepTime`: long — 持续时间(毫秒)
- **返回值**:无
- **调用示例**
```java
axPlayer.playBlockAnimation(100, 64, 200, "open", 1.0, 5, 3000);
```
### `spawnHammerCrackEffect(x, y, z, radius, depth, in, keep, out, mode){:java}`
- 在玩家客户端生成锤击裂纹特效
- **参数**:
- `x` `y` `z`: int — 中心坐标
- `radius`: float — 裂纹半径
- `depth`: float — 裂纹深度
- `in`: int — 淡入时间(毫秒)
- `keep`: int — 保持时间(毫秒)
- `out`: int — 淡出时间(毫秒)
- `mode`: int — 裂纹模式
- **返回值**:无
- **调用示例**
```java
axPlayer.spawnHammerCrackEffect(100, 64, 200, 3.0f, 1.0f, 200, 1000, 500, 0);
```
## 伤害显示
### `addDamageDisplay(damageDisplayConfigId, x, y, z, damage){:java}`
- 在指定坐标为玩家显示伤害数字
- **参数**:
- `damageDisplayConfigId`: String — 伤害显示配置ID
- `x` `y` `z`: double — 显示坐标
- `damage`: double — 伤害数值
- **返回值**:无
- **调用示例**
```java
axPlayer.addDamageDisplay("critical", 100.0, 65.0, 200.0, 999.0);
```
### `addDamageDisplay(damageDisplayConfigId, target, damage){:java}`
- 在目标实体位置为玩家显示伤害数字
- **参数**:
- `damageDisplayConfigId`: String — 伤害显示配置ID
- `target`: Entity — 目标实体
- `damage`: double — 伤害数值
- **返回值**:无
- **调用示例**
```java
axPlayer.addDamageDisplay("default", targetEntity, 50.0);
```
**与 ArcartXEntity.broadcastDamageDisplay 的区别**:
- `ArcartXPlayer.addDamageDisplay` — **点对点**,仅该玩家自身可见
- `ArcartXEntity.broadcastDamageDisplay` — **范围广播**,所有能看到该实体的玩家可见
- `ArcartXEntity.sendDamageDisplayToPlayers` — **指定列表**,仅列表中的玩家可见
## 路标管理
### `addWayPoint(id, title, waypointConfigId, x, y, z){:java}`
- 为玩家添加一个路标
- **参数**:
- `id`: String — 路标唯一标识
- `title`: String — 路标显示标题
- `waypointConfigId`: String — 路标配置ID
- `x` `y` `z`: double — 路标坐标
- **返回值**:无
- **调用示例**
```java
axPlayer.addWayPoint("quest_1", "任务目标", "default", 100.0, 64.0, 200.0);
```
### `deleteWayPoint(id, regex){:java}`
- 删除玩家的路标
- **参数**:
- `id`: String — 路标标识
- `regex`: boolean — 是否使用正则匹配(默认false)
- **返回值**:无
- **调用示例**
```java
axPlayer.deleteWayPoint("quest_1");
```
### `clearWayPoint(){:java}`
- 清除玩家的所有路标
- **参数**:无
- **返回值**:无
- **调用示例**
```java
axPlayer.clearWayPoint();
```
## 额外槽位管理
### `setSlotItemStack(slotID, itemStack){:java}`
- 设置额外槽位的物品,同时更新数据库、客户端显示,并触发 `PlayerExtraSlotUpdateEvent` 事件和更新脚本
- **参数**:
- `slotID`: String — 槽位ID
- `itemStack`: ItemStack — 物品
- **返回值**:无
- **调用示例**
```java
axPlayer.setSlotItemStack("ring_1", itemStack);
```
### `setSlotItemStackOnlyClient(slotID, itemStack){:java}`
- 仅更新客户端显示的槽位物品,不写入数据库
- **参数**:
- `slotID`: String — 槽位ID
- `itemStack`: ItemStack — 物品
- **返回值**:无
- **调用示例**
```java
axPlayer.setSlotItemStackOnlyClient("preview_slot", previewItem);
```
### `removeSlotItemStackOnlyClient(slotID, startWith){:java}`
- 仅从客户端移除槽位物品显示
- **参数**:
- `slotID`: String — 槽位ID
- `startWith`: boolean — 是否匹配以该ID开头的所有槽位
- **返回值**:无
- **调用示例**
```java
axPlayer.removeSlotItemStackOnlyClient("temp_", true); // 移除所有temp_开头的槽位
```
### `getSlotItemStack(slotID){:java}`
- 获取额外槽位中的物品
- **参数**:`slotID`: String — 槽位ID
- **返回值**:`ItemStack?` — 物品对象,可能为null
- **调用示例**
```java
ItemStack item = axPlayer.getSlotItemStack("ring_1");
```
### `syncSlotCacheToClient(){:java}`
- 将所有槽位缓存同步到客户端,通常在玩家重新连接时使用
- **参数**:无
- **返回值**:无
- **调用示例**
```java
axPlayer.syncSlotCacheToClient();
```
## 物品冷却
### `setTagCooldown(tag, time){:java}`
- 设置物品冷却标签的冷却时间
- **参数**:
- `tag`: String — 冷却标签
- `time`: long — 冷却时间(毫秒)
- **返回值**:无
- **调用示例**
```java
axPlayer.setTagCooldown("skill_1", 3000); // 3秒冷却
```
### `getTagCooldown(tag){:java}`
- 获取物品冷却标签的剩余冷却时间
- **参数**:`tag`: String — 冷却标签
- **返回值**:long — 剩余冷却时间(毫秒),0表示已冷却完毕
- **调用示例**
```java
long remaining = axPlayer.getTagCooldown("skill_1");
```
## 音效
### `playSoundForSelf(resourcePath, soundCategory, pitch, keepTime){:java}`
- 为玩家自身播放音效
- **参数**:
- `resourcePath`: String — 音效资源路径
- `soundCategory`: String — 音效类别
- `pitch`: float — 音调
- `keepTime`: int — 持续时间(毫秒)
- **返回值**:无
- **调用示例**
```java
axPlayer.playSoundForSelf("sounds/ui_click.ogg", "master", 1.0f, 1000);
```
## 其他功能
### `sendCustomPacket(id, data...){:java}`
- 向玩家客户端发送自定义数据包
- **参数**:
- `id`: String — 数据包ID
- `data`: String... — 数据内容(可变参数)
- **返回值**:无
- **调用示例**
```java
axPlayer.sendCustomPacket("my_plugin:update", "key1", "value1");
```
### `parseShimmer(code){:java}`
- 在玩家客户端执行Shimmer脚本代码
- **参数**:`code`: String — Shimmer脚本代码
- **返回值**:无
- **调用示例**
```java
axPlayer.parseShimmer("Chat.open(\"Hello!\")");
```
### `sendChatCard(cardID, cardData){:java}`
- 向玩家发送聊天卡片消息
- **参数**:
- `cardID`: String — 卡片配置ID
- `cardData`: Map<String, String> — 卡片数据
- **返回值**:无
- **调用示例**
```java
Map data = new HashMap<>();
data.put("title", "任务完成");
data.put("reward", "100金币");
axPlayer.sendChatCard("quest_complete", data);
```
---
## ArcartXEffectManager:特效管理器
URL: https://wiki.arcartx.com/docs/server_api/5_effect_manager
## ArcartXEffectManager
- 特效管理器提供了模型特效、世界贴图特效和基岩粒子的**范围广播**发送能力。
- 通过 `ArcartXAPI.getEffectManager()` 获取。
- 所有方法都是Kotlin扩展函数,在Java中作为静态方法调用。
**范围广播 vs 点对点**:本类所有方法都是**范围广播**模式。
- `World.xxx()` 系列 — 向指定位置128格范围内的所有玩家发送
- `Entity.xxx()` 系列 — 向所有能看到该实体的玩家发送
如果你只需要让单个玩家看到特效,请使用 `ArcartXPlayer` 的对应方法(点对点发送)。
## 模型特效
### `World.spawnModelEffect(location, modelID, modelScale, keepTime, glow){:java}`
- 在世界指定位置生成一次性模型特效,128格内所有玩家可见
- **参数**:
- `location`: Location — 生成位置
- `modelID`: String — 模型ID
- `modelScale`: float — 模型缩放
- `keepTime`: int — 持续时间(毫秒)
- `glow`: boolean — 是否发光
- **返回值**:无
- **调用示例**
```java
// Kotlin
world.spawnModelEffect(location, "explosion", 2.0f, 3000, true)
// Java
ArcartXEffectManager.spawnModelEffect(world, location, "explosion", 2.0f, 3000, true);
```
### `Entity.spawnModelEffect(modelID, modelScale, keepTime, glow, effectPosition){:java}`
- 在实体身上生成一次性模型特效,所有能看到该实体的玩家可见
- **参数**:
- `modelID`: String — 模型ID
- `modelScale`: float — 模型缩放
- `keepTime`: int — 持续时间(毫秒)
- `glow`: boolean — 是否发光
- `effectPosition`: EffectPosition — 特效位置
- **返回值**:无
- **调用示例**
```java
// Kotlin
entity.spawnModelEffect("aura", 1.0f, 5000, true, EffectPosition.followEntity(entity))
// Java
ArcartXEffectManager.spawnModelEffect(entity, "aura", 1.0f, 5000, true,
EffectPosition.followEntity(entity));
```
### `World.spawnModelEffect(identifier, location, modelID, animation, speed, modelScale, keepTime, glow){:java}`
- 在世界指定位置生成带标识符的模型特效,可通过标识符移除
- **参数**:
- `identifier`: String — 特效唯一标识符
- `location`: Location — 生成位置
- `modelID`: String — 模型ID
- `animation`: String — 动画名称
- `speed`: double — 动画播放速度
- `modelScale`: float — 模型缩放
- `keepTime`: int — 持续时间(毫秒)
- `glow`: boolean — 是否发光
- **返回值**:无
- **调用示例**
```java
// Kotlin
world.spawnModelEffect("portal_1", location, "portal", "spin", 1.0, 1.5f, -1, true)
// Java
ArcartXEffectManager.spawnModelEffect(world, "portal_1", location, "portal", "spin",
1.0, 1.5f, -1, true);
```
### `Entity.spawnModelEffect(identifier, modelID, animation, speed, modelScale, keepTime, glow, effectPosition){:java}`
- 在实体身上生成带标识符的模型特效
- **参数**:
- `identifier`: String — 特效唯一标识符
- `modelID`: String — 模型ID
- `animation`: String — 动画名称
- `speed`: double — 动画播放速度
- `modelScale`: float — 模型缩放
- `keepTime`: int — 持续时间(毫秒)
- `glow`: boolean — 是否发光
- `effectPosition`: EffectPosition — 特效位置
- **返回值**:无
- **调用示例**
```java
// Kotlin
entity.spawnModelEffect("shield", "shield_model", "idle", 1.0, 1.0f, -1, true,
EffectPosition.followEntity(entity))
// Java
ArcartXEffectManager.spawnModelEffect(entity, "shield", "shield_model", "idle", 1.0,
1.0f, -1, true, EffectPosition.followEntity(entity));
```
### `World.removeModelEffect(identifier, location){:java}`
- 移除世界中指定标识符的模型特效
- **参数**:
- `identifier`: String — 特效唯一标识符
- `location`: Location — 参考位置(用于确定广播范围)
- **返回值**:无
- **调用示例**
```java
// Kotlin
world.removeModelEffect("portal_1", location)
// Java
ArcartXEffectManager.removeModelEffect(world, "portal_1", location);
```
### `Entity.removeModelEffect(identifier){:java}`
- 移除实体身上指定标识符的模型特效
- **参数**:`identifier`: String — 特效唯一标识符
- **返回值**:无
- **调用示例**
```java
// Kotlin
entity.removeModelEffect("shield")
// Java
ArcartXEffectManager.removeModelEffect(entity, "shield");
```
## 世界贴图特效
### `World.spawnWorldTextureEffect(location, identifier, worldTexture, effectPosition){:java}`
- 在世界指定位置生成世界贴图特效,128格内所有玩家可见
- **参数**:
- `location`: Location — 参考位置(用于确定广播范围)
- `identifier`: String — 贴图唯一标识
- `worldTexture`: WorldTextureBuilder — 贴图构建器
- `effectPosition`: EffectPosition — 特效位置
- **返回值**:无
- **调用示例**
```java
WorldTextureBuilder builder = new WorldTextureBuilder()
.setTexture("effects/circle.png", true, true)
.setSize(128.0, 128.0)
.setLifeTime(5000);
// Kotlin
world.spawnWorldTextureEffect(location, "magic_circle", builder,
EffectPosition.location(location))
// Java
ArcartXEffectManager.spawnWorldTextureEffect(world, location, "magic_circle", builder,
EffectPosition.location(location));
```
### `Entity.spawnWorldTextureEffect(identifier, worldTexture, effectPosition){:java}`
- 在实体身上生成世界贴图特效,所有能看到该实体的玩家可见
- **参数**:
- `identifier`: String — 贴图唯一标识
- `worldTexture`: WorldTextureBuilder — 贴图构建器
- `effectPosition`: EffectPosition — 特效位置
- **返回值**:无
- **调用示例**
```java
// Kotlin
entity.spawnWorldTextureEffect("name_tag", builder, EffectPosition.followEntity(entity))
// Java
ArcartXEffectManager.spawnWorldTextureEffect(entity, "name_tag", builder,
EffectPosition.followEntity(entity));
```
## 基岩粒子
### `Entity.spawnBedrockParticle(particleID, effectPosition){:java}`
- 在实体身上生成基岩粒子,所有能看到该实体的玩家可见
- **参数**:
- `particleID`: String — 粒子ID
- `effectPosition`: EffectPosition — 特效位置
- **返回值**:无
- **调用示例**
```java
// Kotlin
entity.spawnBedrockParticle("flame", EffectPosition.followEntity(entity))
// Java
ArcartXEffectManager.spawnBedrockParticle(entity, "flame",
EffectPosition.followEntity(entity));
```
### `World.spawnBedrockParticle(location, particleID, effectPosition){:java}`
- 在世界指定位置生成基岩粒子,128格内所有玩家可见
- **参数**:
- `location`: Location — 参考位置(用于确定广播范围)
- `particleID`: String — 粒子ID
- `effectPosition`: EffectPosition — 特效位置
- **返回值**:无
- **调用示例**
```java
// Kotlin
world.spawnBedrockParticle(location, "explosion", EffectPosition.location(location))
// Java
ArcartXEffectManager.spawnBedrockParticle(world, location, "explosion",
EffectPosition.location(location));
```
## 同质接口对比总结
ArcartX中有多个类提供了功能相似但发送方式不同的方法,请根据你的需求选择合适的版本:
**基岩粒子 spawnBedrockParticle**:
| 所在类 | 发送方式 | 适用场景 |
|--------|----------|----------|
| `ArcartXEffectManager` (Entity扩展) | 范围广播(能看到实体的玩家) | 技能特效、战斗粒子等所有人可见的效果 |
| `ArcartXEffectManager` (World扩展) | 范围广播(128格内玩家) | 世界事件、环境粒子等 |
| `ArcartXPlayer` | 点对点(仅该玩家) | UI粒子、个人提示等仅自己可见的效果 |
**世界贴图 WorldTexture**:
| 所在类 | 发送方式 | 适用场景 |
|--------|----------|----------|
| `ArcartXEffectManager` (Entity/World扩展) | 范围广播 | 公共标识、世界装饰等 |
| `ArcartXPlayer` (addWorldTexture) | 点对点 | 个人HUD、私有标记等 |
**伤害显示 DamageDisplay**:
| 所在类 | 发送方式 | 适用场景 |
|--------|----------|----------|
| `ArcartXEntity` (broadcastDamageDisplay) | 范围广播(能看到实体的玩家) | 公共伤害数字 |
| `ArcartXEntity` (sendDamageDisplayToPlayers) | 指定玩家列表 | 部分玩家可见的伤害 |
| `ArcartXPlayer` (addDamageDisplay) | 点对点 | 仅攻击者可见的伤害数字 |
---
## EffectPosition与WorldTextureBuilder:特效数据类
URL: https://wiki.arcartx.com/docs/server_api/6_effect_data
## EffectPosition
- `EffectPosition` 用于描述特效的生成位置,支持两种模式:固定世界坐标和跟随实体。
- 通过静态工厂方法创建实例。
### 固定坐标模式
### `EffectPosition.location(x, y, z, pitch, yaw){:java}`
- 创建一个固定世界坐标的特效位置
- **参数**:
- `x` `y` `z`: double — 世界坐标
- `pitch`: float — 垂直旋转角度(可选,默认0)
- `yaw`: float — 水平旋转角度(可选,默认0)
- **返回值**:`EffectPosition`
- **调用示例**
```java
EffectPosition pos = EffectPosition.location(100.0, 64.0, 200.0);
EffectPosition posWithRotation = EffectPosition.location(100.0, 64.0, 200.0, 45.0f, 90.0f);
```
### `EffectPosition.location(location){:java}`
- 从Bukkit Location创建固定坐标特效位置
- **参数**:`location`: Location — Bukkit位置对象
- **返回值**:`EffectPosition`
- **调用示例**
```java
EffectPosition pos = EffectPosition.location(player.getLocation());
```
### `EffectPosition.location(location, roll){:java}`
- 从Bukkit Location创建固定坐标特效位置,附带翻滚角
- **参数**:
- `location`: Location — Bukkit位置对象
- `roll`: float — 翻滚角度
- **返回值**:`EffectPosition`
- **调用示例**
```java
EffectPosition pos = EffectPosition.location(location, 30.0f);
```
### 跟随实体模式
### `EffectPosition.followEntity(entity){:java}`
- 创建一个跟随实体的特效位置,默认跟随实体的俯仰和偏航
- **参数**:`entity`: Entity — 要跟随的实体
- **返回值**:`EffectPosition`
- **调用示例**
```java
EffectPosition pos = EffectPosition.followEntity(player);
```
### `EffectPosition.followEntity(entity, pitch, yaw, followPitch, followYaw){:java}`
- 创建一个跟随实体的特效位置,可自定义旋转和跟随选项
- **参数**:
- `entity`: Entity — 要跟随的实体
- `pitch`: float — 初始垂直旋转角度
- `yaw`: float — 初始水平旋转角度
- `followPitch`: boolean — 是否跟随实体俯仰
- `followYaw`: boolean — 是否跟随实体偏航
- **返回值**:`EffectPosition`
- **调用示例**
```java
EffectPosition pos = EffectPosition.followEntity(player, 0f, 0f, false, true);
```
### `EffectPosition.followEntity(entity, xOffset, yOffset, zOffset, pitch, yaw, roll, followPitch, followYaw){:java}`
- 创建一个跟随实体的特效位置,完整参数版本
- **参数**:
- `entity`: Entity — 要跟随的实体
- `xOffset` `yOffset` `zOffset`: double — 相对实体的偏移量
- `pitch`: float — 垂直旋转角度
- `yaw`: float — 水平旋转角度
- `roll`: float — 翻滚角度
- `followPitch`: boolean — 是否跟随实体俯仰
- `followYaw`: boolean — 是否跟随实体偏航
- **返回值**:`EffectPosition`
- **调用示例**
```java
// 跟随玩家,向上偏移2格,仅跟随偏航不跟随俯仰
EffectPosition pos = EffectPosition.followEntity(player,
0.0, 2.0, 0.0, 0f, 0f, 0f, false, true);
```
### `EffectPosition.followEntity(uuid, xOffset, yOffset, zOffset, pitch, yaw, roll, followPitch, followYaw){:java}`
- 通过UUID创建跟随实体的特效位置
- **参数**:
- `uuid`: UUID — 实体UUID
- 其余参数同上
- **返回值**:`EffectPosition`
- **调用示例**
```java
EffectPosition pos = EffectPosition.followEntity(entityUUID,
0.0, 1.0, 0.0, 0f, 0f, 0f, true, true);
```
---
## WorldTextureBuilder
- `WorldTextureBuilder` 用于构建世界贴图特效的参数,采用Builder链式调用模式。
### `setTexture(texture, facing, glowing){:java}`
- 设置贴图路径和显示属性
- **参数**:
- `texture`: String — 贴图资源路径
- `facing`: boolean — 是否始终朝向玩家视角
- `glowing`: boolean — 是否发光(不受光照影响)
- **返回值**:`WorldTextureBuilder`(链式调用)
- **调用示例**
```java
builder.setTexture("effects/magic.png", true, true);
```
### `setSize(width, height){:java}`
- 设置贴图尺寸
- **参数**:
- `width`: double — 宽度
- `height`: double — 高度
- **返回值**:`WorldTextureBuilder`
- **调用示例**
```java
builder.setSize(256.0, 256.0);
```
### `setLifeTime(lifeTime){:java}`
- 设置贴图生命周期
- **参数**:`lifeTime`: int — 持续时间(毫秒),-1为永久
- **返回值**:`WorldTextureBuilder`
- **调用示例**
```java
builder.setLifeTime(-1); // 永久显示
```
### 动画方法
- 以下方法用于为世界贴图添加各种动画效果,所有动画方法参数格式一致。
**通用参数**:
- `delay`: int — 延迟开始时间(毫秒)
- `from`: double — 起始值
- `to`: double — 结束值
- `duration`: int — 动画持续时间(毫秒)
- `loop`: boolean — 是否循环播放
| 方法 | 说明 |
|----------------------------------------------------------|--------|
| `addOffsetXAnimation(delay, from, to, duration, loop)` | X轴偏移动画 |
| `addOffsetYAnimation(delay, from, to, duration, loop)` | Y轴偏移动画 |
| `addOffsetZAnimation(delay, from, to, duration, loop)` | Z轴偏移动画 |
| `addScaleAnimation(delay, from, to, duration, loop)` | 缩放动画 |
| `addRotationXAnimation(delay, from, to, duration, loop)` | X轴旋转动画 |
| `addRotationYAnimation(delay, from, to, duration, loop)` | Y轴旋转动画 |
| `addRotationZAnimation(delay, from, to, duration, loop)` | Z轴旋转动画 |
- **调用示例**
```java
WorldTextureBuilder builder = new WorldTextureBuilder()
.setTexture("effects/circle.png", true, true)
.setSize(128.0, 128.0)
.setLifeTime(-1)
.addOffsetYAnimation(0, 0.0, 0.5, 2000, true) // 上下浮动
.addRotationYAnimation(0, 0.0, 360.0, 3000, true) // 持续旋转
.addScaleAnimation(0, 0.8, 1.2, 1500, true); // 缩放呼吸效果
```
---
## ArcartXAreaManager:区域管理器
URL: https://wiki.arcartx.com/docs/server_api/7_area_manager
## ArcartXAreaManager
- 区域管理器负责管理ArcartX的自定义区域,支持区域的增删查操作。
- 通过 `ArcartXAPI.getAreaManager()` 获取。
- 内部使用Chunk索引优化查询性能,支持区域优先级。
## `getArea(location){:java}`
- 获取指定位置所在的区域,如果有多个重叠区域则返回优先级最高的
- **参数**:`location`: Location — Bukkit位置对象
- **返回值**:`Area?` — 区域对象,可能为null
- **调用示例**
```java
Area area = ArcartXAPI.getAreaManager().getArea(player.getLocation());
if (area != null) {
// 玩家在某个区域内
}
```
## `getArea(name){:java}`
- 按名称获取区域
- **参数**:`name`: String — 区域名称
- **返回值**:`Area?` — 区域对象,可能为null
- **调用示例**
```java
Area area = ArcartXAPI.getAreaManager().getArea("spawn_area");
```
## `addArea(name, loc1, loc2){:java}`
- 添加一个新区域,两个位置必须在同一个世界
- **参数**:
- `name`: String — 区域名称
- `loc1`: Location — 对角位置1
- `loc2`: Location — 对角位置2
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getAreaManager().addArea("my_area", loc1, loc2);
```
如果两个位置不在同一个世界,或者已存在同名区域,会抛出 `IllegalArgumentException`。
## `addArea(player, name, loc1, loc2){:java}`
- 添加一个新区域,带玩家消息反馈
- **参数**:
- `player`: Player — 接收反馈消息的玩家
- `name`: String — 区域名称
- `loc1`: Location — 对角位置1
- `loc2`: Location — 对角位置2
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getAreaManager().addArea(player, "my_area", loc1, loc2);
```
## `removeArea(name){:java}`
- 移除指定名称的区域,同时删除对应的配置文件
- **参数**:`name`: String — 区域名称
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getAreaManager().removeArea("my_area");
```
---
## ArcartXKeyBindRegistry:按键绑定注册器
URL: https://wiki.arcartx.com/docs/server_api/8_keybind_registry
## ArcartXKeyBindRegistry
- 按键绑定注册器用于注册和管理自定义按键绑定。
- 通过 `ArcartXAPI.getKeyBindRegistry()` 获取。
- ArcartX支持两种按键类型:**简单按键(SimpleKey)** 和 **客户端按键(ClientKey)**。
**SimpleKey vs ClientKey**:
- **SimpleKey** — 服务端定义的按键组合,按键名称固定,玩家无法自定义。适合内部功能快捷键。
- **ClientKey** — 在客户端按键设置界面中显示的按键,玩家可以自行修改绑定。适合面向玩家的功能按键。
## 简单按键
### `registerSimpleKeyBind(keyName, keys){:java}`
- 注册一个简单按键绑定(无回调)
- **参数**:
- `keyName`: String — 按键唯一标识
- `keys`: List<String> — 按键组合列表(如 `["LEFT_ALT", "R"]`)
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getKeyBindRegistry().registerSimpleKeyBind("my_key",
Arrays.asList("LEFT_CONTROL", "E"));
```
### `registerSimpleKeyBind(keyName, keys, callBack){:java}`
- 注册一个简单按键绑定,使用 `KeyCallBack` 接口处理按下和释放事件(适用于Java)
- **参数**:
- `keyName`: String — 按键唯一标识
- `keys`: List<String> — 按键组合列表
- `callBack`: KeyCallBack — 按键回调接口
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getKeyBindRegistry().registerSimpleKeyBind("my_key",
Arrays.asList("LEFT_ALT", "Q"),
new KeyCallBack() {
@Override
public void onPress(Player player) {
// 按下时执行
}
@Override
public void onRelease(Player player) {
// 释放时执行
}
});
```
### `registerSimpleKeyBind(keyName, keys, onPress, onRelease){:java}`
- 注册一个简单按键绑定,分别指定按下和释放的回调(适用于Kotlin)
- **参数**:
- `keyName`: String — 按键唯一标识
- `keys`: List<String> — 按键组合列表
- `onPress`: PlayerCallBack — 按下回调
- `onRelease`: PlayerCallBack — 释放回调
- **返回值**:无
- **调用示例**
```kotlin
ArcartXAPI.getKeyBindRegistry().registerSimpleKeyBind("my_key",
mutableListOf("LEFT_ALT", "Q"),
onPress = { player -> /* 按下 */ },
onRelease = { player -> /* 释放 */ }
)
```
### `unRegisterSimpleKeyBind(keyName){:java}`
- 注销一个简单按键绑定
- **参数**:`keyName`: String — 按键唯一标识
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getKeyBindRegistry().unRegisterSimpleKeyBind("my_key");
```
## 客户端按键
### `registerClientKeyBind(keyName, category, defaultKey){:java}`
- 注册一个客户端按键绑定(无回调)
- **参数**:
- `keyName`: String — 按键唯一标识
- `category`: String — 按键分类(在客户端设置界面中的分组名)
- `defaultKey`: String — 默认绑定的按键
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getKeyBindRegistry().registerClientKeyBind("open_menu", "我的插件", "G");
```
### `registerClientKeyBind(keyName, category, defaultKey, callBack){:java}`
- 注册一个客户端按键绑定,使用 `KeyCallBack` 接口
- **参数**:
- `keyName`: String — 按键唯一标识
- `category`: String — 按键分类
- `defaultKey`: String — 默认绑定的按键
- `callBack`: KeyCallBack — 按键回调接口
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getKeyBindRegistry().registerClientKeyBind("open_menu", "我的插件", "G",
new KeyCallBack() {
@Override
public void onPress(Player player) {
// 打开菜单
}
@Override
public void onRelease(Player player) { }
});
```
### `registerClientKeyBind(keyName, category, defaultKey, onPress, onRelease){:java}`
- 注册一个客户端按键绑定,分别指定回调(适用于Kotlin)
- **参数**:
- `keyName`: String — 按键唯一标识
- `category`: String — 按键分类
- `defaultKey`: String — 默认绑定的按键
- `onPress`: PlayerCallBack — 按下回调
- `onRelease`: PlayerCallBack — 释放回调
- **返回值**:无
- **调用示例**
```kotlin
ArcartXAPI.getKeyBindRegistry().registerClientKeyBind("open_menu", "我的插件", "G",
onPress = { player -> /* 按下 */ },
onRelease = { player -> /* 释放 */ }
)
```
### `unRegisterClientKeyBind(keyName){:java}`
- 注销一个客户端按键绑定
- **参数**:`keyName`: String — 按键唯一标识
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getKeyBindRegistry().unRegisterClientKeyBind("open_menu");
```
---
## ArcartXUIRegistry:UI注册器
URL: https://wiki.arcartx.com/docs/server_api/9_ui_registry
## ArcartXUIRegistry
- UI注册器负责管理ArcartX的自定义UI界面的注册、打开、关闭和数据通信。
- 通过 `ArcartXAPI.getUIRegistry()` 获取。
- 提供安全版本和Unsafe版本两套方法。
**安全版本 vs Unsafe版本**:
- **安全版本**(`open`、`close`、`sendPacket`、`run`)— 会检查UI是否已注册,通过注册的UI对象操作
- **Unsafe版本**(`openUnsafe`、`closeUnsafe` 等)— 直接发送网络包,不检查注册状态,适用于动态UI或特殊场景
## 注册与注销
### `register(id, src){:java}`
- 注册一个UI界面,支持三种数据源
- **参数**:
- `id`: String — UI唯一标识
- `src`: YamlConfiguration / String / File — UI配置数据源
- **返回值**:`ArcartXUI` — UI对象
- **调用示例**
```java
// 从文件注册
ArcartXUI ui = ArcartXAPI.getUIRegistry().register("my_ui", new File("ui/my_ui.yml"));
// 从YAML字符串注册
ArcartXUI ui = ArcartXAPI.getUIRegistry().register("my_ui", yamlString);
// 从YamlConfiguration注册
ArcartXUI ui = ArcartXAPI.getUIRegistry().register("my_ui", yamlConfig);
```
### `unregister(id){:java}`
- 注销一个UI界面
- **参数**:`id`: String — UI唯一标识
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getUIRegistry().unregister("my_ui");
```
### `reload(id, src){:java}`
- 热重载一个UI界面,会保留已注册的回调,并自动同步到所有在线玩家
- **参数**:
- `id`: String — UI唯一标识
- `src`: YamlConfiguration / String / File — 新的UI配置数据源
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getUIRegistry().reload("my_ui", new File("ui/my_ui.yml"));
```
## 安全操作
### `open(player, id){:java}`
- 为玩家打开一个已注册的UI
- **参数**:
- `player`: Player — 目标玩家
- `id`: String — UI唯一标识
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getUIRegistry().open(player, "my_ui");
```
### `open(player, id, callBack){:java}`
- 为玩家打开UI,并注册一个打开回调
- **参数**:
- `player`: Player — 目标玩家
- `id`: String — UI唯一标识
- `callBack`: CallBack — 打开回调
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getUIRegistry().open(player, "my_ui", () -> {
// UI打开后执行
});
```
### `close(player, id){:java}`
- 为玩家关闭一个已注册的UI
- **参数**:
- `player`: Player — 目标玩家
- `id`: String — UI唯一标识
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getUIRegistry().close(player, "my_ui");
```
### `sendPacket(player, id, handlerName, packet){:java}`
- 向玩家客户端的UI发送数据包
- **参数**:
- `player`: Player — 目标玩家
- `id`: String — UI唯一标识
- `handlerName`: String — 处理器名称
- `packet`: Object — 数据包内容
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getUIRegistry().sendPacket(player, "my_ui", "update_data", dataMap);
```
### `run(player, id, code){:java}`
- 在玩家客户端的UI中执行Shimmer脚本
- **参数**:
- `player`: Player — 目标玩家
- `id`: String — UI唯一标识
- `code`: String — Shimmer脚本代码
- **返回值**:无
- **调用示例**
```java
ArcartXAPI.getUIRegistry().run(player, "my_ui", "updateTitle(\"新标题\")");
```
## Unsafe操作
Unsafe方法直接发送网络包,不检查UI是否已注册。适用于动态创建的UI或需要绕过注册检查的特殊场景。
### `openUnsafe(player, id){:java}`
- 直接发送打开UI的网络包
- **参数**:
- `player`: Player — 目标玩家
- `id`: String — UI标识
- **返回值**:无
### `openUnsafe(player, id, callBack){:java}`
- 直接发送打开UI的网络包,并注册回调
- **参数**:
- `player`: Player — 目标玩家
- `id`: String — UI标识
- `callBack`: CallBack — 打开回调
- **返回值**:无
### `closeUnsafe(player, id){:java}`
- 直接发送关闭UI的网络包
- **参数**:
- `player`: Player — 目标玩家
- `id`: String — UI标识
- **返回值**:无
### `sendPacketUnsafe(player, id, handlerName, packet){:java}`
- 直接发送UI数据包
- **参数**:
- `player`: Player — 目标玩家
- `id`: String — UI标识
- `handlerName`: String — 处理器名称
- `packet`: Object — 数据包内容
- **返回值**:无
### `runUnsafe(player, id, code){:java}`
- 直接在UI中执行脚本
- **参数**:
- `player`: Player — 目标玩家
- `id`: String — UI标识
- `code`: String — Shimmer脚本代码
- **返回值**:无
---
## 开发概述
URL: https://wiki.arcartx.com/docs/server_api
## 写在前面
- ArcartX 提供了完整的服务端 API,允许第三方插件与 ArcartX 深度集成。你可以通过 API 控制模型、特效、UI、按键绑定、音效等几乎所有客户端功能。
- 本章节面向有 Java/Kotlin 开发经验的插件开发者。如果你只是想通过配置文件使用 ArcartX 的功能,请参阅核心教学部分。
## 环境要求
- Java 17+
- Kotlin 1.8.22+(如果使用Kotlin开发)
- 服务端需安装ArcartX插件
## 引入依赖
ArcartX 使用 TabooLib 框架,你的插件不需要依赖 TabooLib,只需要将 ArcartX 作为依赖引入即可。
在你的 `plugin.yml` 中添加依赖声明:
```yaml
depend: [ArcartX]
```
或者作为软依赖:
```yaml
softdepend: [ArcartX]
```
将 ArcartX 的 jar 文件添加到项目的编译依赖中即可使用 API。
## 获取API入口
- ArcartX的所有API都通过 `ArcartXAPI` 这个入口类获取,它提供了7个静态方法,分别返回各个功能模块的管理器单例。
```java
// 获取各个管理器
ArcartXAPI.getEntityManager(); // 实体管理
ArcartXAPI.getEffectManager(); // 特效管理
ArcartXAPI.getUIRegistry(); // UI注册
ArcartXAPI.getKeyBindRegistry(); // 按键绑定
ArcartXAPI.getSoundPlayer(); // 音效播放
ArcartXAPI.getNetworkSender(); // 网络发送
ArcartXAPI.getAreaManager(); // 区域管理
```
## 注意事项
- 请确保在 ArcartX 加载完成后再调用 API,建议在你插件的 `onEnable` 中使用。
- 部分 API 涉及网络数据包发送,请注意线程安全问题,涉及 Bukkit API 的操作需要在主线程执行。
- ArcartX 的实体管理器会自动清理过期的实体缓存,你不需要手动管理实体对象的生命周期。
---
## 玩家模型控制器
URL: https://wiki.arcartx.com/docs/core/10_controller/1_controller
## 什么是控制器
控制器是一套动画状态机,用来自动管理玩家模型的动画切换。简单来说:你定义好"什么情况播什么动画",控制器会在每个游戏刻自动判断玩家当前行为,切换到对应的动画。
举个例子:玩家站着播待机动画,走路播行走动画,跑步播跑步动画——这些切换逻辑就是控制器在做的事。
## 注册方式
控制器只能通过服务端 API 注册,ArcartX 不再内置配置文件管理。这是因为控制器通常由上层插件(如克洛诺斯)动态管理,内置配置反而不灵活。
## 快速上手
下面是一个最简单的控制器配置,只有三个状态:待机、行走、跑步。
```yaml
main:
initial_state: idle
states:
run:
animation: 跑步
walk:
animation: 走路
idle:
animation: 待机
```
这段配置的含义:
1. `main` 是子控制器的名称,你可以随意命名
2. `initial_state: idle` 表示玩家初始处于 `idle` 状态
3. `states` 下定义了三个状态,每个状态绑定一个动画
控制器每个游戏刻会从上到下检查状态条件:先看玩家是否在跑步 → 再看是否在走路 → 都不是就落到 `idle`。`idle` 的条件永远成立,所以它是兜底状态。
状态的判断顺序就是你在配置中写的顺序(从上到下)。把优先级高的状态写在前面。
## 状态名的两种类型
状态名分为两种:
- 保留名:如 `idle`、`walk`、`run`、`swim` 等,控制器会自动判断玩家行为来触发。完整列表见[状态保留名](/docs/core/10_controller/2_state_name)
- 自定义名:任何非保留名的状态(如 `attack1`、`attack2`),不会被自动触发,只能通过服务端 API 或指令手动切换。适用于连招、技能等需要外部控制的场景
## 状态属性
每个状态支持以下配置项:
| 配置键 | 类型 | 默认值 | 说明 |
|:-----------|:-------:|:-----:|:---------------------------------------|
| animation | string | "" | 播放的动画名称 |
| speed | double | 1.0 | 动画播放速度 |
| weight | double | 1.0 | 动画权重(多控制器混合时使用) |
| inTick | int | 5 | 进入该状态时的动画过渡时长(tick) |
| outTick | int | -1 | 离开该状态时的过渡时长(tick),-1 表示使用下一个状态的 inTick |
| in | map | {} | 过渡入动画映射,key 为来源状态名,value 为过渡动画名 |
| to | map | {} | 过渡出动画映射,key 为目标状态名,value 为过渡动画名 |
| exclusive | boolean | false | 独占模式,动画播放完成前不会切换到其它状态 |
| moveLimit | double | 1.0 | 移动速度限制倍率,多个状态叠加时相乘 |
| onStart | string | "" | 进入状态时执行的 Shimmer 脚本 |
| onEnd | string | "" | 离开状态时执行的 Shimmer 脚本 |
| clientLock | object | {} | 客户端输入锁定配置 |
clientLock、onStart 和 onEnd 仅在控制器作用于客户端当前玩家自身时生效。
下面逐个解释关键属性的用法。
### 过渡时长(inTick / outTick)
动画切换不是瞬间跳变的,而是有一个平滑过渡。`inTick` 控制进入时的过渡帧数,`outTick` 控制离开时的过渡帧数。
- `inTick: 0` 表示瞬间切换,没有过渡(适合攻击动画这种需要立即响应的场景)
- `outTick: -1`(默认)表示离开时的过渡时长由下一个状态的 `inTick` 决定
### 过渡动画(in / to)
有时候两个状态之间需要一段专门的过渡动画,而不是简单的混合过渡。
```yaml
states:
run:
animation: 长剑-跑步-跑步中
to:
idle: 长剑-跑步-结束
```
这段配置的意思是:当从 `run` 切换到 `idle` 时,先播放 `长剑-跑步-结束` 这个过渡动画,播完后再进入 `idle` 的待机动画。
`in` 是反过来的——指定从某个状态进入当前状态时的过渡动画。
### 独占模式(exclusive)
开启 `exclusive: true` 后,该状态的动画必须播放完毕才会切换到下一个状态。典型用途是攻击动画——你不希望挥刀到一半就被打断。
### 移动限制(moveLimit)
`moveLimit` 可以在某个状态下限制玩家的移动速度。值为 0~1 的倍率,`0.5` 表示移动速度减半,`0` 表示完全不能移动。多个子控制器的 moveLimit 会相乘。
### 客户端输入锁定(clientLock)
```yaml
clientLock:
input:
- LOCK
- DIRECTION
action:
- JUMP
- SNEAK
```
`input` 支持以下值:
- `LOCK` — 禁用自由相机锁定(通常用于近战吸附的相机解耦)
- `DIRECTION` — 锁定移动方向输入
`action` 支持以下值:
- `SNEAK` — 禁止下蹲
- `JUMP` — 禁止跳跃
- `MOVE` — 禁止所有方向的移动输入
## 实战示例:长剑武器控制器
下面是一个完整的长剑武器控制器配置,包含待机、行走、跑步和三段连击:
```yaml
main:
initial_state: idle
states:
run:
speed: 1
animation: 长剑-跑步-跑步中
to:
idle: 长剑-跑步-结束
clientLock:
input:
- LOCK
walk:
animation: 长剑-行走-走路中
clientLock:
input:
- LOCK
idle:
animation: 长剑-待机
clientLock:
input:
- LOCK
attack1:
animation: 长剑-普攻-2
inTick: 0
outTick: 0
exclusive: true
moveLimit: 0.5
clientLock:
input:
- LOCK
- DIRECTION
attack2:
animation: 长剑-普攻-3
inTick: 0
outTick: 0
exclusive: true
moveLimit: 0.5
clientLock:
input:
- LOCK
- DIRECTION
attack3:
animation: 长剑-普攻-4
inTick: 0
outTick: 0
exclusive: true
moveLimit: 0.5
clientLock:
input:
- LOCK
- DIRECTION
```
逐段解读:
- `run`、`walk`、`idle` 是保留名状态,控制器自动判断切换。跑步状态结束时会播放 `长剑-跑步-结束` 过渡动画再回到待机
- 三个状态都锁定了视角输入(`LOCK`),玩家在这些状态下,如果相机为自定义预设相机且开启了自由相机,左右键输入不会被切换到锁定模式。
- `attack1`、`attack2`、`attack3` 是自定义状态,不会被自动触发,需要服务端插件在玩家攻击时依次切换(实现三段连击)
- 攻击状态设置了 `exclusive: true`,动画播完才能切换;`inTick: 0` 和 `outTick: 0` 让攻击动画瞬间切入切出,手感更利落
- 攻击时 `moveLimit: 0.5` 让玩家移动速度减半,同时锁定视角和移动方向,防止攻击时乱跑
## 多控制器混合
- 一个控制器配置中可以包含多个子控制器,它们并行运行。
- 你可以通过权重设置,实现特定的混合效果。
典型用法:主控制器(`main`)控制全身动作,副控制器(`secondary`)控制上半身动作(攻击、使用物品等)。
```yaml
main:
initial_state: idle
states:
idle:
animation: 待机
walk:
animation: 走路
run:
animation: 跑步
secondary:
initial_state: empty
states:
empty:
animation: empty
inTick: 1
right_eat:
animation: eat_mainhand
left_eat:
animation: eat_offhand
attack1:
animation: 挥剑1
exclusive: true
attack2:
animation: 挥剑2
exclusive: true
attack3:
animation: 挥剑3
exclusive: true
```
这个配置中:
- `main` 负责全身的移动动画
- `secondary` 负责上半身的手部动画。`empty` 是一个不包含任何骨骼动画的空动作,作为副控制器的默认状态——当玩家没有使用物品或攻击时,副控制器不干预任何骨骼
- `right_eat`、`left_eat` 是保留名,玩家进食时自动触发
- `attack1`~`attack3` 是自定义连招状态,由服务端插件控制切换
副控制器的默认状态(如 `empty`)需要对应一个实际存在但不包含任何骨骼动画的空动作,这样它才不会覆盖主控制器的动画。
---
## 状态保留名
URL: https://wiki.arcartx.com/docs/core/10_controller/2_state_name
## 状态保留名
### 基础状态
| 状态名 | 触发条件 |
|:-----------|:-------------------|
| idle | 始终为 true(作为默认状态使用) |
| walk | 正在移动且速度 > 0.1 |
| run | 正在移动且冲刺 |
| sneak | 下蹲 |
| sneak_walk | 下蹲且移动(速度 > 0.05) |
| jump | 跳跃中 |
| die | 死亡 |
### 特殊移动
| 状态名 | 触发条件 |
|:------------|:-----------|
| swim | 游泳 |
| swim_stand | 在水中(非游泳姿态) |
| fly | 创造模式飞行 |
| fall_fly | 鞘翅滑翔 |
| climb | 匍匐 |
| climb_walk | 匍匐移动 |
| ladder_up | 梯子上爬 |
| ladder_down | 梯子下爬 |
| ladder_idle | 梯子上静止 |
### 骑乘
| 状态名 | 触发条件 |
|:----------|:-------|
| ride | 骑乘任意实体 |
| ride_pig | 骑猪 |
| ride_boat | 骑船 |
### 战斗与物品使用
以下状态区分主手(right)和副手(left):
| 状态名 | 触发条件 |
|:-----------------------------------------|:-------|
| sword | 主手挥剑 |
| punch | 主手空手攻击 |
| break_right / break_left | 挥动手臂 |
| bow_right / bow_left | 拉弓 |
| crossbow_right / crossbow_left | 弩蓄力/持弩 |
| trident_throw_right / trident_throw_left | 投掷三叉戟 |
| shield_block_right / shield_block_left | 盾牌格挡 |
| eat_right / eat_left | 进食/饮用 |
| spyglass_right / spyglass_left | 望远镜 |
| toot_horn_right / toot_horn_left | 山羊角 |
| brush_right / brush_left | 刷子 |
| use_right / use_left | 通用使用物品 |
如果状态名不匹配任何内置条件,该状态不会被自动触发,但可以通过外部 API 手动切换到该状态。这适用于连招等需要外部插件控制的场景。
---
## 基岩粒子系统
URL: https://wiki.arcartx.com/docs/core/11_bedrockparticle/1_start
## 简介
你可以使用 [Snowstorm 编辑器](https://snowstorm.app/) 制作粒子,然后直接在 ArcartX 中使用。
## 粒子文件加载
粒子文件通过 ArcartX 的资源目录加载,放置在客户端 `ArcartX/resource/particle/` 文件夹下。
### 目录结构
### 加载步骤
在 Snowstorm 编辑器中制作粒子效果,或者下载现成的粒子文件。
将粒子文件(`.particle.json` 或 `.json`)放入 `ArcartX/resource/particle/` 文件夹。
将粒子使用的贴图(`.png`)放在同一目录下,文件名与粒子文件保持一致。
例如粒子文件为 `magic.particle.json`,贴图文件应为 `magic.png`。
重载客户端资源,查看日志确认粒子加载成功。日志中输出的名称就是粒子 ID。
### 粒子 ID 规则
粒子 ID = 文件相对于 `particle/` 目录的路径(不含后缀)。
例如:
- `particle/magic.particle.json` → ID 为 `magic`
- `particle/effects/fire.particle.json` → ID 为 `effects/fire`
## 其它说明
- 基岩粒子通常用于模型定位器发射或者MM / API中调用,本章节无其它可讲解内容,对于联动功能每个章节内都有所说明。
---
## 如何安装 ArcartX
URL: https://wiki.arcartx.com/docs/core/1_base/1_setup
## 安装前提
ArcartX 由两部分组成:服务端插件 + 客户端 MOD。两者需要配合使用。
你需要准备:
1. 一个 Bukkit 系服务端(Spigot / Paper 及其分支均可,不支持 Sponge)
2. 一个安装了对应 ModLoader 的 Minecraft 客户端
## 安装流程
前往 ArcartX 下载中心 下载对应的文件。
你需要下载两个 jar:
- 服务端插件(文件名通常以 Bukkit 结尾)
- 客户端 MOD(文件名以 ModLoader 名称结尾,如 Forge、Fabric)
将服务端插件放入服务端的 `plugins` 文件夹,将客户端 MOD 放入客户端的 `mods` 文件夹。
启动服务端,ArcartX 会在 `plugins/ArcartX` 下生成默认配置文件。
启动客户端,在 MOD 列表中确认 ArcartX 已加载。
## BungeeCord / Velocity 跨服
如果你使用了 BungeeCord 或 Velocity 进行跨服,需要额外安装信道插件来打通通讯:
在下载中心找到 ArcartXChannel,将其放入 BungeeCord / Velocity 的 `plugins` 文件夹(不是游戏服的 plugins)。
## 客户端拓展
ArcartX 支持模块化的客户端拓展组件。拓展组件既不是 MOD 也不是插件,有专门的安装位置。
不要将客户端拓展放入 `mods` 或 `plugins` 文件夹,否则不会生效。
安装位置:打开客户端的资源包目录(`.minecraft/resourcepacks`),首次启动游戏后会自动生成 `ArcartX` 文件夹:
将客户端拓展的 jar 文件放入 `expansion` 文件夹即可。
## 安装完成
到这里 ArcartX 就安装好了。后续文档会假设你有基本的开服经验(了解插件配置、YAML 语法等)。如果遇到问题,可以加入 QQ 群 832063293 寻求帮助。
---
## 基础配置
URL: https://wiki.arcartx.com/docs/core/1_base/2_setting
## 配置文件位置
配置文件 `setting.yml` 位于服务端 `plugins/ArcartX/` 目录下。
YAML 文件对缩进敏感,请确保每个配置项的缩进正确。
## 配置项详解
### 调试模式
```yaml
# 是否开启调试模式
debug: false
```
开启后会在控制台输出详细的调试信息,正常使用时保持关闭即可。
### 许可证
```yaml
# 许可证配置
# 前往 https://arcartx.com/resources/eula/view 接受 EULA 协议后获取
licenseId: 0
licenseKey: ""
```
ArcartX 是免费的,不填许可证也不影响功能使用。设置许可证的目的是确认你已阅读并接受 EULA 协议,同时帮助识别非官方渠道的付费转载。
### 数据库
```yaml
database:
# 关闭则使用 SQLite 本地存储
enable: false
hostName: "127.0.0.1"
port: "3306"
database: "database"
username: "root"
password: "root"
maxConnections: 4
connectionTimeout: 10000
validationTimeout: 3000
idleTimeout: 60000
loginTimeout: 5
maxLifetime: 180000
maximumPoolSize: 10
minimumIdle: 5
readOnly: false
properties:
- "useSSL=false"
- "useUnicode=true"
- "characterEncoding=utf-8"
- "serverTimezone=UTC"
```
支持 SQLite 和 MySQL 两种存储方式。如果你的服务器是单服架构,保持 `enable: false` 使用 SQLite 即可。需要跨服数据同步时,开启 MySQL 并填写连接信息。
`maxConnections` 的默认值为 CPU 核心数 × 2。
### 加密资源包
```yaml
encryptedResourceFiles:
Example:
# 位于 ArcartX/resource/ 目录下的加密压缩文件名
fileName: "Example.zip"
# 解压密码
password: "123456789"
```
加密资源包需要放在客户端 `ArcartX/resource/` 目录下。
仅支持 zip 格式,压缩时请选择 AES256 加密算法。如果你使用的不是 WinRAR,请在压缩选项中手动指定加密方式。
压缩包内的路径和文件名不要使用中文。
关于加密安全性:没有绝对安全的加密方案,客户端加密资源始终存在被提取的可能。建议对重要资源进行版权留存证明,以便维权。
### 客户端标题
```yaml
clientTitle: "欢迎使用ArcartX,该标题可在setting.yml修改"
```
玩家进入服务器后,客户端窗口标题会显示为此处设置的文字。
### 占位符黑名单
```yaml
placeholderBlacklist:
- "Example_"
```
当客户端通过 Shimmer 脚本请求 PlaceholderAPI 占位符时,匹配此列表的请求会被拦截。支持前缀匹配,比如填写 `Player_` 会拦截所有以 `Player_` 开头的占位符请求。
适用场景:某些占位符计算开销较大,可以通过黑名单阻止客户端频繁请求。
### 脚本类导入
```yaml
script_imports:
Bukkit: "org.bukkit.Bukkit"
ArcartXAPI: "priv.seventeen.artist.arcartx.api.ArcartXAPI"
PlayerUtils: "priv.seventeen.artist.arcartx.util.PlayerUtils"
ItemStackUtils: "priv.seventeen.artist.arcartx.util.ItemStackUtils"
```
用于服务端 JS 脚本中导入 Java/Kotlin 类。key 是脚本中使用的别名,value 是完整类路径。如果你不编写服务端脚本,不需要修改此项。
### CRC64 拓展检测
```yaml
crc64:
# 是否启用客户端拓展 CRC64 检测
enable: false
# 全匹配模式:true 需要完全匹配,false 允许缺少部分拓展
allowPartial: false
list: []
```
用于校验玩家客户端安装的 ArcartX 拓展是否与服务端一致。OP 不受检测限制,可以使用 `/a Crc64 update` 命令将当前客户端的拓展 CRC64 列表同步到服务端。普通玩家如果不匹配会被踢出。
### 实体缓存清理间隔
```yaml
# 单位:tick(6000 tick ≈ 5 分钟)
entityCacheClearInterval: 6000
```
ArcartX 实体管理器的缓存清理周期。一般保持默认值即可。
### 资源同步
```yaml
resourceSync:
# 是否启用资源同步
enable: false
# 资源更新 API 后端地址
url: ""
# API 密钥
apiKey: ""
```
配合 ArcartX 资源管理后端使用,可以实现服务端资源自动下发到客户端。需要先搭建资源管理后端(详见社区资源),获取 API 地址和密钥后填入此处。
---
## 客户端配置
URL: https://wiki.arcartx.com/docs/core/1_base/3_client_config
## 配置文件位置
配置文件 `config.json` 位于客户端 `.minecraft/resourcepacks/ArcartX/setting/` 目录下。首次启动客户端时会自动生成默认配置。
## 默认配置
```json
{
"preload_resources": [],
"font_shadow": true,
"pixel_font": true,
"global_font": false,
"font_baseline_offset": 0.0,
"font_scale_offset": 0.0
}
```
## 配置项详解
### 资源预加载
```json
"preload_resources": []
```
填写资源的相对路径列表,客户端启动时会对这些本地资源进行预加载,将它们提前缓存到内存中。适用于需要在进服后立即显示、不希望出现异步加载延迟的资源。
示例:
```json
"preload_resources": [
"ui/background.png",
"ui/logo.png",
"effect/particle.png"
]
```
仅对本地资源(非压缩包内的加密资源)生效。网络资源和 ZIP 内资源不受此配置影响。
### 字体阴影
```json
"font_shadow": true
```
控制 ArcartX 字体渲染引擎在替换全局文字时是否绘制文字阴影。设为 `false` 后,替换原版文字渲染不再渲染阴影。
### 像素字体识别
```json
"pixel_font": true
```
控制是否启用像素字体自动识别。开启时,ArcartX 会根据字体名称中的关键词(`pixel`、`点阵`、`像素`)自动识别像素字体,并使用专用的像素渲染模式(关闭抗锯齿,使用 Pixel Shader)。
设为 `false` 后,所有字体统一走平滑 SDF 文字渲染,不再区分像素字体。适用于希望所有字体都保持平滑渲染效果的场景。
### 全局字体替换
```json
"global_font": false
```
控制是否启用全局字体替换。开启后,ArcartX 的字体渲染引擎将接管 Minecraft 原版的所有文字渲染,使用 ArcartX 的字体替代默认字体。默认关闭,开启后原版文字可使用ArcartX特殊渲染,但是可能和同质插件产生冲突。
### 字体基线偏移
```json
"font_baseline_offset": 0.0
```
调整全局字体替换渲染的基线垂直偏移量。正值向下偏移,负值向上偏移。用于微调全局字体替换文字在 UI 中的垂直对齐位置。
### 字体缩放偏移
```json
"font_scale_offset": 0.0
```
调整全局字体替换字体渲染的缩放偏移量。正值放大,负值缩小。用于微调全局字体替换文字的整体大小。
---
## 客户端资源目录
URL: https://wiki.arcartx.com/docs/core/1_base/4_resource
## ArcartX 资源目录结构
ArcartX 的资源目录位于 `.minecraft/resourcepacks`
### 目录结构
### 目录说明
| 目录/文件 | 说明 |
|:--------------------|:-----------------------------|
| resource/ | 资源文件根目录,存放贴图、模型、加密压缩包等 |
| resource/model/ | 模型文件目录,详见模型章节 |
| resource/particle/ | 基岩粒子文件目录,详见基岩粒子章节 |
| resource/shader/ | 着色器文件目录,详见 Shader 章节 |
| resource/item_icon/ | 物品图标文件目录,用于自定义物品贴图 |
| resource/pack/ | 原版材质包目录,放入的材质包会强制加载且客户端内无法移除 |
| mouse.png | 鼠标贴图,可替换为自定义图片 |
除 `mouse.png` 外,其余目录均可打包到加密压缩包中(路径保持一致即可)。加密压缩包放入 `resource` 目录下,仅支持 ZIP 格式且压缩格式为 AES256 加密。
如果图片资源包含三角形、圆形等像素不连续的贴图,可以将文件名添加 `_linear` 后缀(如 `xxx_linear.png`),该后缀的图像会进行多重采样以渲染更平滑的效果。
### 资源路径约定
后续文档中,"资源路径"指 `resource/` 目录下的相对路径:
- `abc.png` — 对应 `ArcartX/resource/abc.png`
- `xxx/abc.png` — 对应 `ArcartX/resource/xxx/abc.png`
- 网络资源直接填写直连地址,如 `https://arcartx.com/logo.png`
### 资源加载说明
- 为防止资源过多,ArcartX并非全量加载所有资源,而是根据不同文件类型或大小等因素进行冷热数据/持久数据处理,确保尽可能节省资源,且不会因为资源过多使客户端内存溢出。
- 涉及原版资源包的功能(物品图标、Shader、强制加载的资源包)在无变动时不会触发 MC 资源包全量重载。但如果这些功能使用了加密资源,进入服务器时必定触发重载
- 如果服务器安装了过多 MOD 导致资源加载缓慢,建议将涉及原版材质包功能的内容不进行加密
使用压缩包加密时,路径和文件名不要使用中文。
---
## 物品额外渲染
URL: https://wiki.arcartx.com/docs/core/2_simple/10_item_effect
## 物品额外渲染
物品额外渲染(ItemEffect)可以根据物品的 NBT 标签匹配,在物品图标上叠加额外的渲染图层。常见用途包括品质边框、稀有度光效等。
配置文件位于服务端 `plugins/ArcartX/item_effect/` 目录下,支持创建多个 yml 文件和子目录。
## 配置格式
```yaml
示例:
# NBT 匹配键,支持多级路径(用 . 分隔)
matchKey: "品质"
# NBT 匹配值(忽略大小写)
matchValue: "传说"
# 是否在物品图标之前渲染(默认 false,即渲染在物品之上)
before: false
# 渲染属性
attribute:
w: 16 # 宽度
h: 16 # 高度
x: 0 # X 偏移
y: 0 # Y 偏移
path: "item/legendary.png" # 资源路径
```
## 字段说明
| 字段 | 类型 | 默认值 | 说明 |
|:---------------|:-------:|:-----:|:--------------------------------------------------|
| matchKey | string | "" | NBT 匹配键,支持多级路径如 `display.Name` |
| matchValue | string | "" | NBT 匹配值,忽略大小写 |
| before | boolean | false | 为 true 时渲染在物品图标之前(作为底层),为 false 时渲染在物品图标之上(作为覆盖层) |
| attribute.w | number | 16 | 渲染宽度 |
| attribute.h | number | 16 | 渲染高度 |
| attribute.x | number | 0 | X 轴偏移 |
| attribute.y | number | 0 | Y 轴偏移 |
| attribute.path | string | "" | 贴图资源路径 |
在 UI 中,物品图标的渲染尺寸为 16×16,所以铺满整个物品背景的 ItemEffect 应设置为 16×16。
## 使用示例
为"传说"品质的物品添加金色边框:
```yaml
传说边框:
matchKey: "品质"
matchValue: "传说"
before: false
attribute:
w: 16
h: 16
x: 0
y: 0
path: "item/legendary_border.png"
```
为所有物品添加底层背景(渲染在物品之前):
```yaml
物品底色:
matchKey: "品质"
matchValue: "传说"
before: true
attribute:
w: 16
h: 16
x: 0
y: 0
path: "item/legendary_bg.png"
```
---
## 自定义物品贴图
URL: https://wiki.arcartx.com/docs/core/2_simple/1_item_texture
## 自定义物品贴图
ArcartX 可以通过 NBT 将物品渲染为指定的贴图样式。
## 使用方法
准备好物品贴图资源文件,放入客户端资源目录的 `resource/item_icon` 中。如果该文件夹不存在,手动创建即可。
将物品贴图放入文件夹,支持三种格式:
1. 直接放入 — 渲染为原始贴图,以物品形式手持
2. 文件名添加 `_handheld` 后缀(如 `xxx_handheld.png`)— 以工具形式手持
3. 序列帧贴图 — 需要同时放入对应的 `.mcmeta` 文件
注意:该文件夹只识别 PNG 格式,GIF 等其他格式不会被加载。
三种格式放入后的目录结构:
启动客户端后,使用指令设置物品贴图。手持一个物品,执行:
`/a item setIcon item`
其他格式的效果:
`/a item setIcon icon`
`/a item setIcon sword_handheld`
如果贴图文件在子文件夹中,路径格式为 `xxx/xxx`。
ArcartX 通过读取物品的 `icon` NBT 来判断贴图,因此也可以通过其他支持 NBT 编辑的插件来设置。
MythicMobs 配置示例:
```yaml
# MythicMobs 物品库配置
TestItem:
Id: DIAMOND_SWORD
Data: 0
Display: '&3测试物品'
Lore:
- ''
Options:
HideFlags: true
Unbreakable: true
NBT:
icon: 'item'
```
## 原版 GUI 中的物品图标
如果你不想将箱子 UI 替换为 AX UI,但需要自定义箱子 UI 中的物品图标,可以为物品添加 `url` NBT 标签。存在该标签时,GUI 中会渲染 `url` 指定的文件路径。
该方式支持 GIF 和网络链接,但仅在 GUI 中有效,手持等场景无效。可能需要使用支持自定义 NBT 的箱子菜单插件。
---
## 文字渲染与图标
URL: https://wiki.arcartx.com/docs/core/2_simple/2_font_texture
## 文字渲染系统
ArcartX 使用 SDF(Signed Distance Field)技术进行文字渲染,替代了传统的位图渲染方式。同时增加了一些特殊效果:描边、流光、渐变等特效。
如需让ArcartX文字渲染器接管原版渲染,请查看客户端配置相关章节。该功能默认关闭。
## 特殊格式码
除了 Minecraft 原版的格式码(`§0`~`§f`、`§l`、`§o` 等),ArcartX 还支持以下扩展格式码:
### 自定义颜色
```
§#RRGGBB
```
使用 6 位十六进制颜色值指定文字颜色。例如 `§#FF5500` 显示为橙色。
### 描边
```
§s
§s§0
§s§#RRGGBB
```
- `§s` — 开启描边,默认黑色描边
- `§s§0` — 描边 + 使用 MC 色码指定描边颜色
- `§s§#FF0000` — 描边 + 使用 Hex 颜色指定描边颜色
### 渐变色
```
§~RRGGBB-RRGGBB
```
从第一个颜色渐变到第二个颜色,按文字像素位置线性插值。渐变范围从当前位置开始,到遇到 `§r`、新颜色码或新渐变码时结束。
例如 `§~FF0000-00FF00渐变文字§r` 会从红色渐变到绿色。
### 流光(扫光)
```
§^RRGGBB
```
在文字上产生从左到右的高光扫过效果,周期约 1.5 秒。指定的颜色为高光颜色,文字本身保持当前颜色。
例如 `§^FFFFFF流光文字§r` 会产生白色高光扫过效果。
### 荧光笔背景
```
§*RRGGBB
```
为文字添加半透明的背景色(80% 不透明度),类似荧光笔标记效果。
例如 `§*FFFF00高亮文字§r` 会添加黄色荧光笔背景。
### 图标
```
§%000000龘
```
在文字中插入自定义图标。6 位数字为图标 ID(000000~999999),后面跟一个 `龘` 字符作为占位符。
## 转义符号
如果使用ArcartX文字渲染器接管原版渲染,在聊天栏、物品名等位置使用 ArcartX 格式码时,需要通过转义方式输入 `§` 符号:
```
§k!
```
`§k!` 会被替换为 `§` 字符本身。通过这种方式,你可以在聊天栏、物品名等任何位置使用 ArcartX 的文字渲染格式。请注意,由于MC机制,原版不接受任何它不认识的格式,如果同一行有多个该用法,请确保第一个结束之后使用§r清除格式,否则将无法被正常处理,
文字渲染有最小尺寸限制,过小的文字会被限制在可视范围内,不会因为缩放过小而看不清。
## 自定义文字图标
文字图标配置位于服务端 `plugins/ArcartX/font_icon/` 目录下,支持创建多个 yml 文件。
### 配置格式
```yaml
example:
# 图标 ID,取值范围 0 ~ 999999
id: 0
# 图标贴图路径,支持 PNG 和 GIF
path: "icons/smile.png"
# 图标与文字高度的比值(默认 0.8)
proportion: 0.8
```
图标的宽度会根据贴图的长宽比自动计算,不需要手动设置尺寸。
### 使用方式
在文字中使用 `§%000000` 格式插入图标,其中 6 位数字对应图标的 ID。
例如图标 ID 为 1,则使用 `§%000001`。
文字图标在 ArcartX 的 UI(Menu / HUD / Tip)以及自定义聊天栏中生效。配合自定义聊天栏功能,可以实现表情包、动态称号等效果。
---
## Shader
URL: https://wiki.arcartx.com/docs/core/2_simple/3_shader
自 1.21.8 版本起,由于 Mojang 对 Shader 系统进行了大规模重构,ArcartX 已移除对 Shader 的支持。以下内容仅适用于 1.21.8 之前的版本。
## Shader
Shader(着色器)的工作模式类似于"滤镜",可以对游戏画面施加特殊的视觉效果,例如模糊(Blur)、铅笔画等。
1.21.4 版本以后,Shader 文件改为通过数据包加载。你可以通过语句/命令/API 主动开启数据包中定义好的 Shader。以下使用方式为 1.21.4 之前的用法。
## 使用
准备 Shader 文件。Shader 分为 `program` 和 `post` 两个文件夹,放入客户端 `resource/shader` 目录中:
以从 1.7.10 提取的 "pencil" 着色器为例。打开 post 文件后,需要将资源域 ID 修改为 `arcartx`:
```json
{
"targets": [
"swap"
],
"passes": [
{
"name": "arcartx:outline_soft", // 资源域改为 arcartx
"intarget": "minecraft:main",
"outtarget": "swap"
},
{
"name": "arcartx:blit", // 资源域改为 arcartx
"intarget": "swap",
"outtarget": "minecraft:main"
}
]
}
```
该 Shader 包含两个 passes:`outline_soft` 和 `blit`。将它们的 program 文件提取出来,同样修改资源域 ID:
```json
{
"blend": {
"func": "add",
"srcrgb": "one",
"dstrgb": "zero"
},
"vertex": "sobel",
"fragment": "arcartx:outline_soft", // 资源域改为 arcartx
"attributes": [ "Position" ],
"samplers": [
{ "name": "DiffuseSampler" }
],
"uniforms": [
{ "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "InSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] },
{ "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] },
{ "name": "LumaRamp", "type": "float", "count": 1, "values": [ 16.0 ] },
{ "name": "LumaLevel", "type": "float", "count": 1, "values": [ 4.0 ] }
]
}
```
```json
{
"blend": {
"func": "add",
"srcrgb": "one",
"dstrgb": "zero"
},
"vertex": "blit",
"fragment": "arcartx:blit", // 资源域改为 arcartx
"attributes": [ "Position" ],
"samplers": [
{ "name": "DiffuseSampler" }
],
"uniforms": [
{ "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }
]
}
```
将对应的 `.fsh` 和 `.vsh` 文件也放到对应的文件夹中:
进入游戏,重载客户端资源后,使用指令开启着色器(名称取自 post 文件夹中的文件名):
`/a shader start [玩家ID] pencil`
也可以通过 Shimmer 脚本和 API 控制 Shader。
更多 Shader 编写知识请参考 Minecraft Shader 相关教程。
---
## 音效
URL: https://wiki.arcartx.com/docs/core/2_simple/4_sound
## 音效
- 音效文件仅支持 ogg 格式,其他格式(如 mp3)无法加载。
- 音效主要在 API 或 MM 词条中使用,具体说明请参考后续章节。
- 对于ogg格式,你还需要确保是Minecraft能加载的格式,详情查看:[前往链接](https://docs.fabricmc.net/zh_cn/develop/sounds/custom)
---
## 服务端脚本
URL: https://wiki.arcartx.com/docs/core/2_simple/5_scripts
## 服务端脚本
- 服务端脚本使用 JavaScript 编写。如果你不熟悉 JavaScript,建议先学习基础语法,或寻求有经验的开发者协助。
- 服务端脚本用于实现一些简单的功能,或配合其他模块完成特定的功能。
- 默认配置中提供了多个示例供参考。
## 示例配置一览
- 以下是默认脚本示例的内容。安装完成后,你可以在 `ArcartX/scripts` 目录下找到这些示例脚本。
```yaml
####################################################
# 请一定看完所有文字后再进行修改!!!!!!
# 请一定看完所有文字后再进行修改!!!!!!
# 请一定看完所有文字后再进行修改!!!!!!
####################################################
# 脚本目前分为两种类型,一种是普通脚本,一种是事件脚本
# 普通脚本是用于比如按键按下时候的执行脚本、额外槽位放置时候的条件检测脚本、额外槽位物品更新时候的执行脚本等等
# 事件脚本是用于在某些事件发起的时候执行脚本,比如玩家进入游戏时候的执行脚本、玩家移动的时候执行脚本等
# 一些可能的使用效果:
# 1. 按键按下时候给玩家发送消息 / 按键时候通过检测某些条件给玩家变身(如短暂设置模型)
# 2. 额外槽位放置时候检测玩家是否有条件将物品放入槽位,如果条件检测不通过则返回false
# 3. 额外槽位物品更新时候给玩家发送消息 / 额外槽位物品更新时候通过检测某些条件给玩家变身(如短暂设置模型)
# 4. 玩家进入游戏时(事件脚本)给玩家发送消息、通过外部API比如职业插件给玩家设置职业对应的模型等
# ....以此类推,请发挥想象
# 普通脚本(normal)可用常量:
# player -> 玩家自身
# itemStack -> (在操作槽位时有效)槽位物品
# args -> 调用时候传入的参数
# 事件脚本(event)可用常量:
# event -> 事件对象
# 如果你不会请学习js基础或者找你会js的朋友帮助你完成
# 导入类需要手动导入,前往setting.yml的script_imports进行导入你所需要的类(同样这一步你至少要会js基础)
# 关于配置(yml)中允许调用脚本的配置项,可以给脚本传入参数:
# 参数的格式为:参数名 = 参数值,多个参数用分号隔开。例如: {message = 你好;message2 = 你好2}
# 一些建议:
# 1. 请不要在脚本中使用过多的循环,会导致服务器卡顿
# 2. 请不要在脚本中使用过多的递归,会导致服务器卡顿
# 3. 如果您确实会js,应该可以自行甄别哪些操作会导致服务器卡顿,避免使用这些操作
# 4. 关于事件脚本,请不要太过于相信客户端相关的事件,因为客户端是不可信的,以下是一个不安全的实践:
# 在客户端发包事件时让玩家以OP身份执行指令: # 注意 这是一个错误示范!!!
# type: "event"
# target: "priv.seventeen.artist.arcartx.event.client.ClientCustomPacketEvent"
# script: |
# PlayerUtils.static.dispatchOpCommand(player,event.getArg(0));
# 这个脚本会发生什么?当客户端发包时,会以OP身份执行客户端发包中的指令,这是一个非常不安全的操作,请不要这样做。
# 一些实用的例子
###############################################
# >>> 以下这些可能用于比如按键等可以主动触发脚本的场景
###############################################
# 示例0. 给玩家发送Title,配置中调用方式:给玩家发送Title{title = 你好;subtitle = 你好2}
给玩家发送Title:
type: "normal"
script: |
player.sendTitle(args.getString("title"),args.getString("subtitle"));
# 示例1. 给玩家发送消息,配置中调用方式:给玩家发送消息{message = 你好}
给玩家发送消息:
type: "normal"
script: |
player.sendMessage(args.getString("message"));
# 示例2. 让玩家发送一条聊天消息,配置中调用方式:让玩家发送消息{message = 你好}
让玩家发送消息:
type: "normal"
script: |
player.chat(args.getString("message"));
# 示例3. 玩家以OP身份执行一个命令,配置中调用方式:玩家OP执行命令{command = help}
# PS: 这里使用的是基于TabooLib的虚拟OP工具,如果需要玩家执行OP命令请一定使用这个方法,不要使用setOp把玩家真的设置成OP再取消
# 这个示例和上面错误示范的区别在于,这个示例执行的指令来自于服务端,而不是客户端
玩家OP执行命令:
type: "normal"
script: |
PlayerUtils.static.dispatchOpCommand(player,args.getString("command").replace("",player.getName()));
# 示例4. 通过ArcartXAPI让玩家客户端执行Shimmer脚本,配置中调用方式:执行脚本{script = Shimmer.println("Hello World!")}
执行脚本:
type: "normal"
script: |
ArcartXAPI.static.getEntityManager().getPlayer(player).parseShimmer(args.getString("script"));
# 示例5. 以控制台身份执行命令,配置中调用方式:控制台执行命令{command = say 你好! }
控制台执行命令:
type: "normal"
script: |
Bukkit.static.dispatchCommand(Bukkit.static.getConsoleSender(),args.getString("command").replace("",player.getName()));
# 示例6. 通过ArcartXAPI设置玩家模型持续xx毫秒 配置中调用方式:设置玩家模型{model = "model",scale = 1.0,time = 1000}
设置玩家模型:
type: "normal"
script: |
ArcartXAPI.static.getEntityManager().getPlayer(player).tryModel(args.getString("model"),args.getDouble("scale"),args.getInt("time"));
###############################################
# >>> 以下这些可能用于额外槽位放置时候的条件检测脚本
###############################################
# 示例7. 检测玩家是否有权限放置物品到额外槽位,配置中调用方式:检测玩家权限{permission = "example.permission"}
检测玩家权限:
type: "normal"
script: |
var result = player.hasPermission(args.getString("permission"));
if (!result) {
player.sendMessage("你没有权限放置这个物品");
}
return result
# 示例8. 检测玩家等级是否达到要求,配置中调用方式:检测玩家等级{level = 10}
检测玩家等级:
type: "normal"
script: |
var result = player.getLevel() >= args.getInt("level");
if (!result) {
player.sendMessage("你的等级不足");
}
return result
# 示例9. 检测物品是否包含指定lore,配置中调用方式:检测物品包含lore{lore = "lore"}
检测物品包含lore:
type: "normal"
script: |
var result = ItemStackUtils.static.containsLore(itemStack,args.getString("lore").replace("&","§"));
if (!result) {
player.sendMessage("物品不符合要求");
}
return result
# 示例10. 检测物品是否有一行lore是指定内容,配置中调用方式:检测物品lore{lore = "lore"}
检测物品lore:
type: "normal"
script: |
var result = ItemStackUtils.static.hasLore(itemStack,args.getString("lore").replace("&","§"));
if (!result) {
player.sendMessage("物品不符合要求");
}
return result
###############################################
# >>> 以下这些可能用于额外槽位物品更新时候的执行脚本
###############################################
# 示例11. 检测物品的nbt值,如果包含改nbt则将玩家的模型设置位指定模型,配置中调用方式:通过NBT设置模型{key = "xxx.xxx"}
通过NBT设置模型:
type: "normal"
script: |
var nbt = ItemStackUtils.static.getTag(itemStack,args.getString("key"))
if(nbt.isEmpty()) {
return;
}
ArcartXAPI.static.getEntityManager().getPlayer(player).setModel(nbt,1.0);
###############################################
# >>> 以下这些是事件脚本,用于在某些事件发起的时候执行脚本
# PS: 事件不需要导入包,填写完整的类路径+类名即可
###############################################
# 示例12. 玩家进入游戏时给玩家发送消息,配置中调用方式:玩家进入游戏发送消息
玩家进入游戏发送消息:
type: "event"
target: "priv.seventeen.artist.arcartx.event.client.ClientInitializedEvent$End"
script: |
event.getPlayer().sendMessage("你好!" + event.getPlayer().getName() + "我是ArcartX事件脚本发送的消息");
```
## 详细解释
- 后续章节中的区域、按键、槽位等功能都会涉及脚本调用,这里先介绍脚本的基本用法。关于 JavaScript 编写本身,建议系统性学习或直接使用现成的示例。
### 功能性脚本
- 功能性脚本在特定场景下被调用。其中槽位脚本较为特殊,它比其他脚本类型多了一个 `itemStack` 变量,用于检测物品条件或在物品更新后执行额外操作。
- 以下是几个典型示例。限制槽位放置物品:
```yaml
# 示例8. 检测玩家等级是否达到要求,配置中调用方式:检测玩家等级{level = 10}
检测玩家等级:
type: "normal"
script: |
var result = player.getLevel() >= args.getInt("level");
if (!result) {
player.sendMessage("你的等级不足");
}
return result
# 示例9. 检测物品是否包含指定lore,配置中调用方式:检测物品包含lore{lore = "lore"}
检测物品包含lore:
type: "normal"
script: |
var result = ItemStackUtils.static.containsLore(itemStack,args.getString("lore").replace("&","§"));
if (!result) {
player.sendMessage("物品不符合要求");
}
return result
```
- 又比如槽位物品更新后,读取物品的 NBT 进行玩家的模型设置:
```yaml
# 示例11. 检测物品的nbt值,如果包含改nbt则将玩家的模型设置位指定模型,配置中调用方式:通过NBT设置模型{key = "xxx.xxx"}
通过NBT设置模型:
type: "normal"
script: |
var nbt = ItemStackUtils.static.getTag(itemStack,args.getString("key"))
if(nbt.isEmpty()) {
return;
}
ArcartXAPI.static.getEntityManager().getPlayer(player).setModel(nbt,1.0);
```
- 功能性脚本通常包含三个变量:`player`、`itemStack`、`args`。其中 `itemStack` 仅在脚本作用于额外槽位时可用。
- 以 `通过NBT设置模型` 为例,它的调用方式为 `通过NBT设置模型{key = "xxx.xxx"}`,即脚本名加参数。参数由大括号包裹,格式为 `参数名 = 参数值`,多个参数之间用分号隔开。
- 在脚本中,可以通过 `args` 对象的函数获取传入的参数值,具体用法可参考上述示例。
### 事件脚本
- 事件脚本需要一定的编程基础。它会在指定的事件上注册监听器,并在事件触发时执行脚本内容。
- 例如监听玩家进入事件并发送消息。注意,事件脚本只有一个 `event` 变量。
```yaml
# 示例12. 玩家进入游戏时给玩家发送消息,配置中调用方式:无需调用,事件发起则会执行。
玩家进入游戏发送消息:
type: "event"
target: "priv.seventeen.artist.arcartx.event.client.ClientInitializedEvent$End"
script: |
event.getPlayer().sendMessage("你好!" + event.getPlayer().getName() + "我是ArcartX事件脚本发送的消息");
```
---
## 区域管理
URL: https://wiki.arcartx.com/docs/core/2_simple/6_area
## 区域管理
内置的区域管理用于实现进入/离开区域时执行脚本、播放音频、弹出动态效果等功能。
### 创建区域
输入 `/a area tool` 获取区域工具,按照提示编辑区域:
### 配置文件
创建区域后,`area` 目录下会生成对应的配置文件:
```yaml
world: "world"
x1: 80
y1: -45
z1: -86
x2: 50
y2: -61
z2: -67
priority: 0
enter:
- 给玩家发送Title{title = 欢迎;subtitle = 你好}
leave:
- 给玩家发送Title{title = 再见;subtitle = 拜拜}
```
| 字段 | 类型 | 默认值 | 说明 |
|:---------|:------:|:------:|:----------------------|
| world | string | "none" | 区域所在世界 |
| x1/y1/z1 | int | 0 | 区域角点 1 坐标 |
| x2/y2/z2 | int | 0 | 区域角点 2 坐标 |
| priority | int | 0 | 区域优先级,多个区域重叠时数值大的优先生效 |
| enter | list | [] | 进入区域时执行的脚本列表 |
| leave | list | [] | 离开区域时执行的脚本列表 |
### 副本世界兼容
-对于副本插件动态生成的世界(如 `dungeon_副本名_编号`),只需在副本的原世界中创建区域即可。ArcartX 会自动识别此类命名格式并匹配。`dungeon_test_1` 的原世界就是`test`
---
## 额外槽位
URL: https://wiki.arcartx.com/docs/core/2_simple/7_slot
## 额外槽位
额外槽位用于在 ArcartX 的自定义 UI 中创建自定义物品格子(如装备栏、时装栏等)。
配置文件位于服务端 `plugins/ArcartX/extra_slot/` 目录下,支持创建多个 yml 文件。
## 配置格式
```yaml
Slot1: # 配置项名作为槽位 ID,不要重复
# 槽位属性系统
# 可选值:none(不启用)、AttributePlus(需要 3.0+)、AstraXHero、CraneAttribute
attribute: "none"
# 槽位限制脚本(可选,不需要限制可删除此项)
limit:
- "检测玩家等级{level = 10}"
# 物品更新后执行的脚本(可选)
update:
- "给玩家发送消息{message = 你更新了你的槽位物品}"
# 是否加载模型
loadSubstitutionModel: false
```
## 字段说明
| 字段 | 类型 | 默认值 | 说明 |
|:----------------------|:-------:|:------:|:-----------------------------------|
| attribute | string | "none" | 槽位属性系统,物品放入后自动应用属性 |
| limit | list | 空 | 物品放入限制条件(脚本表达式列表) |
| update | list | 空 | 物品更新后执行的脚本列表 |
| loadSubstitutionModel | boolean | false | 是否启用时装模型功能,开启后以物品 NBT 中的模型信息进行时装穿戴 |
## 在 UI 中使用
在 UI 的 Slot 控件中,将 `slotType` 设为 `Extra`,`id` 填写槽位配置的 ID 即可。
```yaml
slot_example:
type: Slot
attribute:
slotType: ~Extra
id: Slot1
width: 50
height: 50
```
## 时装示例
通过额外槽位实现简单的时装穿戴:
```yaml
时装槽:
attribute: "none"
loadSubstitutionModel: true # 这里改成true
```
如果需要使用时装,需要先将玩家模型替换为 ArcartX 的自定义模型。具体请参考模型章节。
---
## 路标导航
URL: https://wiki.arcartx.com/docs/core/2_simple/8_waypoint
## 路标导航
- 路标导航是 RPG 游戏中常见的功能,用于在 HUD 上显示标记以指引玩家前进方向。
### 配置示例
- 路标配置位于 ArcartX 根目录中的 `waypoint` 目录下,你可以创建多个 yml 配置,只需遵循以下格式新建路标样式即可。
- 路标需要你创建"样式"配置,以在游戏中按照自定义的方式显示。
- 配置格式:
```yaml
# 样式ID
default:
# 常态显示贴图路径
normal: "waypoint/normal.png"
# 路标显示在屏幕边缘时候的两种状态贴图
left: "waypoint/left.png"
right: "waypoint/right.png"
# 贴图渲染宽高
width: 40
height: 40
# 字体
font: ""
# 渲染字号
fontSize: 32
# 联动UI罗盘控件时显示的图标
icon: "xxx.png"
```
- 创建完成后请重载配置。你可以通过以下两种方式显示路标:
1. 通过 `a waypoint` 指令为玩家添加路标
2. 通过 API 控制
- 请注意,ArcartX 仅提供渲染接口,具体任务插件的实现需要你安装额外附属或自行开发管理逻辑。
- 效果展示:
---
## 伤害显示
URL: https://wiki.arcartx.com/docs/core/2_simple/9_damage_display
## 伤害显示
伤害显示用于将伤害数值渲染到世界中。ArcartX 的伤害显示是一个 API,支持多个模板预设,你可以为不同类型的伤害指定不同的显示效果。
### 配置
伤害显示配置位于 `damage_display` 目录下,支持创建多个 yml 文件。
```yaml
# 样式 ID
test:
textureWidth: 32
textureHeight: 32
randomMin: 0
randomMax: 1
decimalPlaces: 0
textures:
- "damage/0.png"
- "damage/1.png"
- "damage/2.png"
- "damage/3.png"
- "damage/4.png"
- "damage/5.png"
- "damage/6.png"
- "damage/7.png"
- "damage/8.png"
- "damage/9.png"
```
### 字段说明
| 字段 | 类型 | 默认值 | 说明 |
|:--------------|:------:|:---:|:------------------------------------------|
| textureWidth | double | 0.0 | 每张数字贴图的宽度 |
| textureHeight | double | 0.0 | 每张数字贴图的高度 |
| randomMin | double | 0.0 | 显示位置的随机偏移最小值(世界坐标单位) |
| randomMax | double | 0.0 | 显示位置的随机偏移最大值(世界坐标单位) |
| decimalPlaces | int | 0 | 小数位数 |
| textures | list | [] | 贴图列表,从 0 到 9 共 10 张图。第 11 张为小数点,第 12 张为逗号 |
### 测试
通过指令测试预设效果:
```
/a damageDisplay test
```
### API 示例
```kotlin
// 在指定坐标显示伤害
player.arcartXHandler?.addDamageDisplay("预设ID", x, y, z, damage)
// 在目标实体位置显示伤害
player.arcartXHandler?.addDamageDisplay("预设ID", target, damage)
```
---
## 基础设定
URL: https://wiki.arcartx.com/docs/core/3_camera/1_setting
ArcartX 提供了全面的自定义相机系统,包括自定义相机位置、八向移动相机、场景相机等功能。
## 相机基础设定
相机的默认设置位于服务端 `plugins/ArcartX/camera/setting.yml`:
```yaml
# 相机功能总开关
enable: true
# 强制第三人称视角
forceMode: 0 # 0-关闭,1-强制第一人称,2-强制第三人称
# 默认使用的预设 ID
default: "idle"
```
如果总开关不开启或者不存在默认预设,相机功能不会正常加载。预设的配置方式请看下一章。
## 第一人称相机控制
ArcartX 支持在第一人称视角下通过模型动画控制相机参数,可控制的参数包括:
- `yaw` — 偏航角
- `pitch` — 俯仰角
- `roll` — 翻滚角
- `x` / `y` / `z` — 相机位置偏移
- `fov` — 视场角
这些参数可以通过 Shimmer 脚本的 Camera 函数进行控制。
## 兼容性说明
Forge 1.20.1 版本支持与 Shoulder Surfing Reloaded 兼容。使用时需要在 ArcartX 中关闭自定义相机功能(`enable: false`),让 Shoulder Surfing Reloaded 接管第三人称视角。
自由相机模式下的车辆类型操作体验已优化,包括 ArcartX 内置的自定义坐骑功能。
---
## 预设相机
URL: https://wiki.arcartx.com/docs/core/3_camera/2_preset
## 相机预设
- 相机预设用于定义游戏中的镜头位置。如果你有完备的运动系统,则可能需要多个预设,例如奔跑时的镜头位置、战斗时的镜头位置等。
- 对于基础运用,只需设置一个默认的相机位置,并在相机基础设置中将其设置为默认预设即可。
- 如果需要动态调整(例如跑步或释放技能时切换镜头),你可能需要进一步了解 API 或动作控制器。Shimmer 中也提供了相应的语句。
### 配置文件格式讲解
相机预设配置位于ArcartX根目录中的 `camera/preset` 目录下。你可以创建多个yml配置文件来定义不同的相机预设。
每个预设配置文件都需要遵循特定的格式。配置项名将作为预设的唯一标识符(ID)。
#### 预设配置示例
```yaml
# 预设ID
idle:
# 相机偏移量设置
offsetX: -0.7 # X轴偏移
offsetY: 0 # Y轴偏移
offsetZ: 10 # Z轴偏移
# 八向移动相机开关
enableFree: true
# 隐藏头部模型 如果使用了自定义模型,使用对应预设相机后将隐藏Head和head骨骼
hideHead: false
# 过渡动画设置
bezier: # 贝塞尔曲线参数
x1: 0.1
y1: 0.25
x2: 0.1
y2: 0.25
transition: 1000 # 过渡时间(毫秒)
```
- 其中贝塞尔曲线参数用于控制过渡时的速率曲线。如果不确定如何配置,使用默认值即可。
- 过渡时间的单位为毫秒,1000 毫秒即 1 秒,表示镜头过渡动画的持续时长。
---
## 场景相机
URL: https://wiki.arcartx.com/docs/core/3_camera/3_scene
## 场景相机
场景相机用于实现复杂的相机运镜效果,通过配置多个步骤来实现相机的平移和旋转。
场景相机分为两种模式:
- 相对模式(mode: 0)— 变换相对于玩家自身坐标,适用于技能等需要完全控制视角的场景,允许移动
- 绝对模式(mode: 1)— 变换基于世界坐标,适用于演绎场景,不允许移动
配置位于 `camera/scene` 目录下,支持创建多个 yml 文件。
### 相对相机
相对模式下,手动配置各位置点的偏移量,在游戏内测试后精调即可。
```yaml
mode: 0 # 0=相对坐标模式 1=绝对坐标模式
backTime: 1000 # 复位时间(毫秒),绝对模式下无过渡直接回原位
step:
step0:
x: 0
y: 1
z: 3
yaw: 90
pitch: 0
bezier: # 变换贝塞尔曲线
x1: 0.1
y1: 0.25
x2: 0.1
y2: 0.25
transition: 800 # 变换时间(毫秒)
keep: 800 # 持续时间(毫秒)
## 后续步骤继续向下添加
```
步骤按照从上到下的顺序依次执行。每个步骤的名称可以自定义,建议使用有意义的名称便于管理。
### 绝对相机
绝对模式需要精确的世界坐标,不推荐手写。ArcartX 提供了游戏内编辑功能:
1. 执行指令 `/a camera createSceneAbs`
2. 在每个路径点按下 Alt 键,游戏内会生成粒子显示路径(红色为路径点连线,蓝色为当前点的朝向)
3. 完成后在聊天栏发送 `end [路径点名称]`(注意是聊天发送,不是指令)
4. 配置文件会自动生成,之后可以进行精细化微调
### 使用方式
场景相机可以通过指令或 API 运行。推荐使用脚本 + API 的方式,避免过度依赖指令。
场景相机 ID 为配置文件名(不含后缀),例如 `test.yml` 的 ID 为 `test`。子文件夹中的配置使用斜杠分隔,例如 `folder/test`。
---
## 全息基础数据
URL: https://wiki.arcartx.com/docs/core/4_hologram/1_data
## 前置知识
从全息系列开始,将涉及 Shimmer 脚本。后续内容默认你已掌握 Shimmer 的基础用法。如果还不熟悉,请先阅读 Shimmer 文档。
## 全息模板
ArcartX 的全息功能基于"模板"机制。创建好模板后,可以在世界全息、实体血条等场景中反复调用。
模板配置位于 `hologram/data` 目录下,支持创建多个配置文件。
```yaml
# 全息宽高,用于确定旋转轴和中心位置(非脚本)
width: 500
height: 500
# 触发器配置
action:
open: # 全息打开时执行的 Shimmer 脚本
close: # 全息关闭时执行的 Shimmer 脚本
# 元素配置
element:
# 可配置贴图和文字两种元素
```
全息的运算在客户端主线程执行,避免在全息中进行大量复杂运算,否则会导致客户端掉帧。
每个全息实例都有独立的 Shimmer 上下文。例如生物 A 的血条和生物 B 的血条互不影响。
## 全息元素
全息由贴图和文字两种元素组成,显示顺序由配置顺序决定,先配置的元素在底层。
### 贴图元素
```yaml
texture:
type: "texture"
attribute:
x: "0" # X 坐标(支持脚本)
y: "0" # Y 坐标(支持脚本)
width: "500" # 宽度(支持脚本)
height: "500" # 高度(支持脚本)
alpha: "1.0" # 透明度(支持脚本)
path: "emoji/test.png" # 贴图路径(静态)
```
### 文字元素
```yaml
example:
type: "text"
attribute:
x: "0" # X 坐标(支持脚本)
y: "0" # Y 坐标(支持脚本)
alpha: "1" # 透明度(支持脚本)
fontSize: 50 # 字号(静态)
lineSpace: 16 # 行距(静态)
texts: # 文本内容(支持脚本)
- "~&1示例文字" # 使用 ~ 开头表示纯文字内容
```
## 完整示例
```yaml
width: 1200
height: 216
action:
open:
close:
element:
texture:
type: "texture"
attribute:
x: "0"
y: "0"
width: "1200"
height: "216"
alpha: "1.0"
path: "output.png"
```
如何将全息显示在世界中或作为血条显示在生物头顶,请参阅后续章节。
---
## 世界全息
URL: https://wiki.arcartx.com/docs/core/4_hologram/2_location
## 世界全息
世界全息用于将全息模板显示在世界中的固定位置,适用于装饰性全息、排行榜等场景。
配置位于 `hologram/location` 目录下。
## 配置文件
```yaml
example:
world: "world" # 显示世界
x: -966 # X 坐标
y: 110 # Y 坐标
z: 186 # Z 坐标
yaw: 50 # 水平旋转角度(默认 50)
pitch: 90 # 垂直倾斜角度(默认 90)
follow: false # 是否跟随玩家视角(默认 false)
hologram: "全息示例" # 全息模板名,对应 data 目录中的模板文件名(不含 .yml 后缀)
```
每个世界全息配置都是一个独立的全息实例,其内部的脚本上下文变量互相隔离。
---
## 实体全息血条
URL: https://wiki.arcartx.com/docs/core/4_hologram/3_entity
## 实体血条
实体血条用于将全息渲染在生物头顶,显示生物血量等信息。
配置位于 `hologram/entity_heal_bar` 目录下。
## 配置格式
```yaml
example:
match: # 匹配的生物名称列表
- "boss" # 填写 default 表示未匹配到其它规则时的默认血条
# 特殊类型:AdyeshachOnly | PlayerOnly | OtherEntity(不包含前两种)
keepTime: 2000 # 显示持续时间,单位毫秒,-1 为永久(默认 2000)
fadeTime: 500 # 淡入淡出时间,单位毫秒(默认 500)
hologram: "测试血条" # 血条模板名,对应 data 目录中的模板文件名(不含 .yml 后缀)
```
匹配规则基于生物的显示名称(不含颜色代码)。如果你不希望玩家也被匹配到,建议在生物名中加入特殊符号加以区分。
### 额外变量
实体血条的全息模板中可以使用以下额外变量:
| 变量 | 说明 |
|:--------------|:-------|
| val.name | 生物名称 |
| val.health | 生物当前血量 |
| val.maxHealth | 生物最大血量 |
---
## 简单自定义按键
URL: https://wiki.arcartx.com/docs/core/5_key/1_simple_key
## 简单自定义按键
- 简单自定义按键允许你通过配置文件,将指定按键绑定到服务端脚本,按下即触发。
- 之所以称为简单按键,是因为通过此方式注册的按键,客户端无法自定义。例如你设置了按键 A 执行 spawn 指令,玩家在客户端无法修改,也无法感知该按键的存在。
## 配置方式
简单按键位于`key_bind/simple_key`目录下。你可以按照以下格式创建多个文件以便分组。
```yaml
示例按键: # 配置项名作为ID 不要重复
keys: # 按键名,列表形式,可以为组合键
- "O"
trigger: # 触发后执行的脚本,请查看脚本如何使用以了解这里如何填写。无需触发直接删掉该配置项即可
- "让玩家发送消息{message = 我按下了示例按键组}"
- "玩家OP执行命令{command = kill }"
# 这里做一个按键按下时候给玩家发送消息并且暂时将玩家模型设置为指定模型的示例
变身:
keys:
- "P"
trigger:
- "给玩家发送消息{message = 你变身了,持续10秒}"
- "设置玩家模型{model = xxx; scale = 0.5; time = 10000}"
```
- 对于简单按键,可以配置多个目标键位以及触发多条脚本。可实现的功能取决于脚本所支持的能力。如果你熟悉 Java 或 Kotlin,也可以直接通过 API 注册按键并自定义触发逻辑。
---
## 自定义客户端按键
URL: https://wiki.arcartx.com/docs/core/5_key/2_client_key
## 自定义客户端按键
自定义客户端按键可以将按键注册到客户端的按键表中,让玩家在客户端设置中自定义键位。适用于技能等需要灵活键位的场景。
## 配置方式
在 `key_bind/client_key` 目录下创建配置文件:
```yaml
获得重生: # 配置项名作为 ID,不要重复
category: "ArcartX 自定义按键" # 在客户端按键设置中显示的分类名
default: "M" # 默认绑定键
```
重载客户端后,在按键绑定页面即可看到注册的按键:
此时按键仅完成注册,不具备任何功能。要让按键触发实际操作,请参阅下一章"自定义按键组"。
---
## 客户端按键组
URL: https://wiki.arcartx.com/docs/core/5_key/3_key_group
## 自定义按键组
- 自定义按键组是指在客户端中自定义按键的组合,在触发的时候执行特定的服务端脚本。
### 配置文件
- 在`key_bind/key_group`目录下创建配置文件:
- 以上一章的客户端按键 ID 为例配置按键组:
```yaml
示例按键组: # 配置项名作为ID 不要重复
keys: # 按键组内的按键 这里填写客户端按键ID
- "获得重生"
trigger: # 触发后执行的脚本,请查看脚本如何使用以了解这里如何填写。无需触发直接删掉该配置项即可
- "让玩家发送消息{message = 我按下了示例按键组}"
# 判断按键顺序的时间间隔(以毫秒为单位)每次按键之间允许的毫秒间隔
interval: 100
```
### 鼠标按键支持
按键组支持监听鼠标按键,可使用以下关键字:
- `mouse_left` - 鼠标左键
- `mouse_right` - 鼠标右键
- `mouse_middle` - 鼠标中键
注意事项:
- 按键组中的按键必须按照配置的顺序触发
- 两次按键之间的间隔不能超过`interval`设定的时间
- 即使按照正确顺序按下所有按键,如果超出间隔时间也不会触发
---
## 客户端按键ID表
URL: https://wiki.arcartx.com/docs/core/5_key/4_key_name
## 按键名列表
这里列出所有的按键ID,我懒得写中文注解了,大概看看应该能看懂。
- HAT_CENTERED
- HAT_UP
- HAT_RIGHT
- HAT_DOWN
- HAT_LEFT
- HAT_RIGHT_UP
- HAT_RIGHT_DOWN
- HAT_LEFT_UP
- HAT_LEFT_DOWN
- KEY_UNKNOWN
- SPACE
- APOSTROPHE
- COMMA
- MINUS
- PERIOD
- SLASH
- 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- SEMICOLON
- EQUAL
- A
- B
- C
- D
- E
- F
- G
- H
- I
- J
- K
- L
- M
- N
- O
- P
- Q
- R
- S
- T
- U
- V
- W
- X
- Y
- Z
- LEFT_BRACKET
- BACKSLASH
- RIGHT_BRACKET
- GRAVE_ACCENT
- WORLD_1
- WORLD_2
- ESCAPE
- ENTER
- TAB
- BACKSPACE
- INSERT
- DELETE
- RIGHT
- LEFT
- DOWN
- UP
- PAGE_UP
- PAGE_DOWN
- HOME
- END
- CAPS_LOCK
- SCROLL_LOCK
- NUM_LOCK
- PRINT_SCREEN
- PAUSE
- F1
- F2
- F3
- F4
- F5
- F6
- F7
- F8
- F9
- F10
- F11
- F12
- F13
- F14
- F15
- F16
- F17
- F18
- F19
- F20
- F21
- F22
- F23
- F24
- F25
- KP_0
- KP_1
- KP_2
- KP_3
- KP_4
- KP_5
- KP_6
- KP_7
- KP_8
- KP_9
- KP_DECIMAL
- KP_DIVIDE
- KP_MULTIPLY
- KP_SUBTRACT
- KP_ADD
- KP_ENTER
- KP_EQUAL
- LEFT_SHIFT
- LEFT_CONTROL
- LEFT_ALT
- LEFT_SUPER
- RIGHT_SHIFT
- RIGHT_CONTROL
- RIGHT_ALT
- RIGHT_SUPER
- MENU
---
## 覆盖模型
URL: https://wiki.arcartx.com/docs/core/6_model/10_fashion
## 覆盖模型
覆盖模型(时装)用于在玩家基底模型之上叠加渲染额外的模型,实现时装、装备外观等功能。ArcartX 提供两种覆盖模式:传统模式和全覆盖模式。
两种模式共享相同的骨骼动画机制:
- 覆盖模型会跟随基底模型的骨骼运动。例如基底模型正在播放 `idle`,覆盖模型也会播放 `idle`
- 如果覆盖模型中存在某个骨骼而基底模型中不存在,则该骨骼会根据覆盖模型自身对应动画的骨骼动作进行变换
- 基底模型的骨骼优先级高于覆盖模型。当两者存在相同骨骼时,以基底模型的动作为准
## 传统模式
传统模式基于标准史蒂夫骨骼结构,支持按部位单件覆盖和全套覆盖,格式类似于龙时的基岩模型时装。玩家基底模型需要包含以下标准骨骼(图中红框标注的部分):
传统模式将覆盖模型分为五个部位,每个部位可以独立穿戴和替换也支持全套套装:
| 部位 | 说明 |
|------|-----------------------|
| 头部 | 头盔、帽子、面具等 |
| 上身 | 胸甲、外套、披风等 |
| 下身 | 腿甲、裤子、裙子等 |
| 鞋 | 靴子、鞋子等 |
| 其它装饰 | 翅膀、尾巴、背饰等不属于上述四个部位的装饰 |
传统模式要求玩家基底模型使用标准史蒂夫骨骼结构,否则覆盖模型无法正确对应部位。
## 全覆盖模式
全覆盖模式适用于非标准史蒂夫骨骼的玩家模型。该模式不区分部位,将整个覆盖模型作为一个整体叠加渲染在基底模型上。
全覆盖模式不要求基底模型使用标准史蒂夫骨骼,适用于自定义骨骼结构的玩家模型,但是不支持单件。
---
## 物品附加模型
URL: https://wiki.arcartx.com/docs/core/6_model/12_item_extra_model
## 物品附加模型
物品模型支持在定位器上额外渲染附加模型。通过在物品的 NBT 中写入附加模型数据,即可在物品模型的指定位置叠加渲染其他模型。
典型应用场景:武器配件系统、装饰挂件、可组合的模块化装备。
普通物品模型和第一人称动画模型均支持此功能。
## 工作原理
- 附加模型渲染在物品模型的指定定位器位置上
- 每个定位器可以绑定一个附加模型
### 定位器依附于骨骼
将定位器创建在某个骨骼的下级,附加模型会继承该骨骼的旋转角度,跟随骨骼运动。
## NBT 数据结构
附加模型数据存储在物品 NBT 的 `extra_model` 复合标签中,每个键值对表示一个定位器与模型的绑定关系:
```json
{
"extra_model": {
"scope_extra": "scope_red_dot",
"muzzle_extra": "suppressor"
}
}
```
| 字段 | 说明 |
|----------|-------------|
| 键(Key) | 物品模型中的定位器名称 |
| 值(Value) | 要挂载的附加模型 ID |
## 使用示例
### 模型准备
1. 在物品模型中创建用于挂载配件的定位器(如 `scope_extra`、`muzzle_extra`),注意,所有额外附加模型定位器需要以`_extra` 结尾。
2. 准备配件模型
### 设置附加模型
- 通过插件 API 或 NBT 编辑工具为物品写入 `extra_model` 数据。
- 也可以直接通过 `/a item setExtraModel ` 进行设置
写入后物品的 NBT 中会包含:
```json
{
"extra_model": {
"scope_extra": "scope_red_dot",
"muzzle_extra": "suppressor"
}
}
```
### 效果预览
每个定位器只能绑定一个附加模型。重复写入同一定位器会覆盖之前的模型。移除某个配件只需删除对应的 NBT 键即可。
---
## 玩家模型附加模型
URL: https://wiki.arcartx.com/docs/core/6_model/13_player_extra_model
## 玩家模型附加模型
附加模型用于在玩家模型上额外渲染一个模型,通过 API 设置,通常用于实现饰品等功能。`注意该功能并不打算用作时装等功能,它是将一个模型渲染在目标模型定位器的位置上并继承旋转`
核心特性:
- 附加模型会执行与玩家模型相同的动作。例如玩家模型正在执行 `idle`,附加模型也会执行 `idle`。如果附加模型没有对应动作则不会播放动画
- 附加模型渲染在玩家模型的定位器位置上。例如玩家模型有 `hat_extra` 定位器,附加模型就会渲染在该定位器的位置上
- 每个定位器可以添加一个附加模型
## 渲染位置
附加模型渲染在目标模型的定位器上。如果定位器有父级骨骼,附加模型会继承该骨骼的旋转角度:
### 定位器依附于骨骼
适用于需要跟随骨骼运动的附加模型(如帽子跟随头部旋转)。
以一个帽子模型为例:
将定位器创建在骨骼的下级,使其依附于该骨骼:
通过 API 将模型 `hat` 设置到 `hat_extra` 定位器上,效果如下:
---
## 开始使用模型
URL: https://wiki.arcartx.com/docs/core/6_model/1_start
## 模型概述
ArcartX 支持两种模型格式:
- bbmodel 格式:BlockBench 的原生格式,可读取 Java 模型、基岩模型、通用模型。推荐使用。
- geo 格式:基岩模型的导出格式(`.geo.json` + `.animation.json` + `.png`)。
bbmodel 中一些复杂的运动方式(如 lk 等)在直接读取时无法解析,需要先在 BlockBench 中导出为 geo 格式然后再导到bbmodel里面
## 模型加载
模型文件放入客户端 `ArcartX/resource/model` 文件夹下。
### bbmodel 格式
将 `.bbmodel` 文件放入 `ArcartX/resource/model` 文件夹。
重载客户端资源(或重启客户端),查看客户端日志确认模型是否加载成功。日志中输出的名称就是后续使用的模型 ID。
如果需要发光贴图,在模型的贴图列表中添加一个名为 `[主贴图名]_glow` 的贴图即可。
### geo 格式
准备好模型文件,按以下命名规则放入 `ArcartX/resource/model` 文件夹:
- `xxx.geo.json` — 模型文件
- `xxx.animation.json` — 动画文件(可选)
- `xxx.png` — 贴图文件
- `xxx.glow.png` — 发光贴图(可选)
重载客户端资源,查看客户端日志确认加载结果。
## axmeta 扩展数据文件
axmeta 文件用于为模型配置额外参数。文件名格式为 `模型名.axmeta.json`,放在模型文件的同级目录下。
```json
{
"glow_level": 0,
"player_skin": false,
"item_scale": 1.0,
"distance": 16,
"hand_offset": [0, 0, 0]
}
```
各字段说明:
| 字段 | 类型 | 默认值 | 说明 |
|:------------|:--------:|:-------:|:----------------------------------|
| glow_level | int | 0 | 发光等级,取值 0~15 |
| player_skin | boolean | false | 是否将贴图替换为玩家皮肤(仅对玩家实体有效) |
| item_scale | double | 1.0 | 物品类型模型的缩放比例,影响物品、方块、特效、掉落物附加模型的尺寸 |
| distance | double | 16 | 方块模型的靠近动画触发距离(格),玩家进入此距离时播放靠近动画 |
| hand_offset | float[3] | [0,0,0] | 第一人称手部模型的偏移量 [x, y, z] |
如果所有字段都使用默认值,不需要创建 axmeta 文件。
### 玩家皮肤贴图
`player_skin` 设为 `true` 时,会将模型的所有贴图替换为玩家皮肤。如果你使用的是多贴图模型,只想让部分贴图使用玩家皮肤,可以将对应贴图命名为 `player_skin.png`,这样只有这张贴图会被替换。
---
## 模型链接
URL: https://wiki.arcartx.com/docs/core/6_model/2_model_link
## 模型链接
模型链接功能可以将其它模型的动作导入到指定模型中,同骨骼模型相互导入动画。
配置文件位于服务端 `plugins/ArcartX/model_link/` 目录下,格式如下:
```yaml
root:
示例:
# 目标模型 ID(要导入动作的模型)
targetModelID: "my_model"
# 要导入的动作来源模型 ID 列表
import:
- "shared_animations_model"
- "another_model"
```
配置加载后会自动同步到客户端。目标模型在播放动画时,如果自身没有对应动作,会从 import 列表中的模型查找。
---
## 含名称的实体模型
URL: https://wiki.arcartx.com/docs/core/6_model/3_named_entity_model
## 根据名称渲染实体模型
- 实体模型的名称匹配配置位于 ArcartX 根目录下的 `entity_model` 目录中,支持创建多个配置文件。
- 配置格式说明
```yaml
example: # 配置项名称,不可重复
matchName: "123456" # 匹配名,无需颜色符号。建议在生物名中添加特殊符号以避免误匹配玩家,因为匹配时不包含颜色代码。
modelID: "test" # 模型 ID,获取方式参见上一章
scale: 1 # 模型缩放
hideNameTag: false # 是否隐藏名称标签,适用于装饰性实体
hurtColor: true # 受击渲染,关闭后受击时不会显示红色闪烁效果
virtualWidth: -1 # 虚拟体积(仅 ADY 实体有效)
virtualHeight: -1 # 虚拟体积(仅 ADY 实体有效)
renderAlways: false # 持续渲染(仅 ADY 实体有效)
```
- 配置完成后,将实体命名为 `matchName` 对应的名称即可看到模型效果。
---
## 物品和方块模型
URL: https://wiki.arcartx.com/docs/core/6_model/4_item_model
## 物品/方块模型
- 物品和方块模型建议使用 `bbmodel` 格式,只有该格式支持调整位置。
- 如果方块模型需要发光(作为方块光源),请参阅模型篇第一章的相关说明,此处不再赘述。
## 设置模型到物品
- 设置物品模型只需通过指令或 NBT 编辑即可完成。
- 指令方式:`/a item setModel [模型ID]`
- NBT 方式:将 `model` 的值设置为模型 ID,你可以使用支持 NBT 编辑的物品库进行设定。
- 以下示范指令方式:手持物品后输入 `/a item setModel test`,其中 `test` 是模型篇第一章中导入的模型。
大型模型的渲染消耗较高。如果是需要长期手持的物品模型,会在HUD和手持位置同时渲染两次。建议为此类物品设置2D贴图,在UI模式下会优先使用2D图标以减少性能消耗。
## 设置模型手持位置
默认情况下模型的手持位置需要调整,请安装 [ArcartX BlockBench 插件](https://arcartx.com/resources/140/) 后在 BlockBench 中进行调整。
## 设置模型到方块
- 设置方块模型的方式与物品相同,区别在于设置的是 `头颅方块`,其余流程完全一致。
- 原版基岩模型不支持 3×3 以上大小的方块模型,按照上述物品模型的步骤进行转换即可突破该限制。
- 方块模型的体积为自动计算,无需担心模型过大导致超出原版体积范围而不渲染的问题。
- 方块模型的渲染结果与 BlockBench 中编辑时的位置一致。
## 方块靠近动画
方块模型支持玩家靠近时自动触发动画。当玩家进入设定距离范围内,方块会依次播放过渡动画和循环动画;离开范围后回到默认待机。
触发距离通过模型的 `axmeta.json` 中的 `distance` 字段配置,默认为 16 格:
```json
{
"distance": 16
}
```
方块模型需要在动画文件中包含以下动画名称:
| 动画名 | 说明 |
|---|---|
| `closeTo_in` | 玩家进入距离范围时播放的过渡动画,播放一次。可选,没有则直接进入 `closeTo` |
| `closeTo` | 玩家在距离范围内时循环播放的动画 |
| `idle` | 默认待机动画,玩家不在范围内时循环播放 |
播放逻辑:玩家进入范围 → 播放 `closeTo_in`(如果有)→ 循环播放 `closeTo` → 玩家离开范围 → 回到 `idle`。
---
## 第一人称模型
URL: https://wiki.arcartx.com/docs/core/6_model/5_first_person
## 第一人称模型
ArcartX 提供两种第一人称模型模式:
1. 渲染玩家当前模型的手臂部分
2. 类似 FPS 游戏的物品专属第一人称动画模型
### 玩家模型手臂渲染
该模式会截取玩家当前模型的 `RightArm` 和 `LeftArm` 两个骨骼,在空手状态下进行第一人称渲染。同时支持覆盖模型(时装)。
由于不同模型的骨骼结构差异,手臂渲染位置可能不正确。此时需要在模型的 `axmeta.json` 中调整 `hand_offset` 字段,该数组包含三个值分别对应 X、Y、Z 轴偏移:
### 物品第一人称动画
该模式为物品提供独立的第一人称渲染,类似 FPS 游戏的武器视角,内置拔出/收起动画的自动调度。
你可以从社区下载 [第一人称示例模型](https://arcartx.com/resources/187/) 作为起点:
要点:
- 将手臂贴图命名为 `player_skin` 即可自动使用玩家皮肤贴图
- 该模式基于史蒂夫手臂骨骼,仅适用于基底模型为史蒂夫骨骼的玩家模型
- 如需支持覆盖模型(时装),请按照示例模型的命名规范命名手臂骨骼
- 需要安装 `camera` 插件,并在根骨骼创建 `camera` 定位器(支持读取 camera 动画,可控制位置、角度和 FOV)
- 模型中至少需要包含 `idle` 动画,否则不会被识别为第一人称动画模型
放入模型目录后,通过指令 `a item setFPModel 模型id` 将手持物品设置为第一人称动画模型:
### 将第三方模型转入 ArcartX
如果你已有现成的第一人称动画模型(如 TaCZ 等模组的模型),需要进行以下适配:
1. 将示例模型的两个手臂骨骼分别复制到原模型手臂骨骼的下级(放在下级可直接跟随原模型动画),删除原模型手臂的显示方块
2. 将原模型的 `camera` 骨骼替换为 ArcartX `camera` 插件的格式
TaCZ 等模组的第一人称模型手臂朝向可能与 ArcartX 不同(如向上 180°),复制示例骨骼时需要相应旋转角度。导入前请务必确认相关模型的版权许可,避免侵权。
---
## 其它模型渲染类型
URL: https://wiki.arcartx.com/docs/core/6_model/6_other_model
## 掉落物附加模型
- 掉落物附加模型用于在渲染掉落物时附加额外的模型效果。以下是一个示例:
- 使用指令 `/a item setDrop drop` 或为物品添加 nbt `drop` 即可生效。
## 箭矢模型
- 箭矢模型需要配合开发使用,将弓箭的实体名称设置为 `model:模型id` 即可。
---
## 模型状态动画名称
URL: https://wiki.arcartx.com/docs/core/6_model/7_animation_name
## 生物状态动画名
生物会在以下状态时播放对应动画,优先级从高到低排列。如果动画文件中不存在对应名称的动画,则跳过该状态,继续检查下一个。
| 动画名 | 触发条件 | 说明 |
|--------------|------------|---------------------------|
| `die` | 实体死亡时 | 播放后定格在最后一帧,实体延迟 5 秒后从世界移除 |
| `swim` | 实体在水中时 | |
| `fly` | 实体在鞘翅滑翔时 | |
| `jump` | 实体跳跃时 | 仅对玩家类型实体生效 |
| `attack` | 实体挥动手臂时 | |
| `damage` | 实体受到伤害时 | |
| `run` | 实体移动中且正在冲刺 | 非潜行状态 |
| `sneak_walk` | 实体潜行并移动时 | |
| `walk` | 实体行走时 | 非潜行状态 |
| `sneak` | 实体潜行静止时 | |
| `idle` | 兜底状态 | 始终满足条件,循环播放 |
服务端可通过 AnimationCommand 下发动画指令,其优先级高于上述所有状态。命令动画支持设置持续时间,过期后自动回退到状态动画。
## 玩家状态动画名
对于玩家,状态机支持自定义。若未设置自定义状态机,则按以下默认逻辑播放动画。
默认状态下,玩家动作分为**主轨道**和**副轨道**两个轨道并行处理,主轨道控制身体姿态,副轨道控制手部动作,两个轨道的动画会混合叠加。
### 主轨道
控制玩家的整体身体姿态。所有动画默认以**循环**方式播放,仅 `die` 为**单次播放并定格**在最后一帧。优先级从高到低:
| 动画名 | 触发条件 | 播放方式 | 过渡时间 |
|---------------|-----------------|------|--------|
| `die` | 玩家死亡 | 单次定格 | 5 tick |
| `ride_pig` | 骑乘猪 | 循环 | 5 tick |
| `ride_boat` | 骑乘船 | 循环 | 5 tick |
| `ride` | 骑乘任何载具(通用) | 循环 | 5 tick |
| `swim` | 玩家正在游泳 | 循环 | 5 tick |
| `swim_stand` | 玩家在水中但未游泳 | 循环 | 5 tick |
| `fly` | 创造模式飞行 | 循环 | 5 tick |
| `fall_fly` | 鞘翅飞行 | 循环 | 5 tick |
| `climb_walk` | 爬行姿态且正在移动(不在水中) | 循环 | 5 tick |
| `climb` | 爬行姿态(不在水中) | 循环 | 5 tick |
| `ladder_up` | 在梯子上向上攀爬 | 循环 | 5 tick |
| `ladder_down` | 在梯子上向下攀爬 | 循环 | 5 tick |
| `ladder_idle` | 在梯子上静止 | 循环 | 5 tick |
| `jump` | 跳跃中 | 循环 | 5 tick |
| `run` | 移动中且冲刺(非潜行) | 循环 | 5 tick |
| `sneak_walk` | 潜行并移动 | 循环 | 5 tick |
| `walk` | 行走(非潜行) | 循环 | 5 tick |
| `sneak` | 潜行静止 | 循环 | 5 tick |
| `idle` | 兜底状态,始终满足 | 循环 | 5 tick |
`die` 动画播放后会定格在最后一帧,实体延迟 5 秒后从世界移除。首次进入某个状态时过渡时间为 0(立即切换),后续状态切换才使用表中的过渡时间。
### 副轨道
控制玩家的手部动作,与主轨道动画通过**混合权重**叠加播放。
副轨道的动画分为两种播放模式:
- **单次播放**:动画播放一次后才允许切换到新状态,播放期间即使触发条件不再满足也不会中断。
- **连击序列**:多个动画按顺序循环播放(如 `sword_1` → `sword_2` → `sword_3` → `sword_1` ...),整个序列循环执行。
混合权重说明:
- 权重 `1`:副轨道动画以完整权重叠加到主轨道上。
- 权重 `-1`:副轨道动画以特殊混合方式叠加,通常用于单手动作,避免覆盖主轨道的身体姿态。
优先级从高到低:
| 动画名 | 触发条件 | 播放方式 | 过渡时间 | 权重 |
|-----------------------------------|----------------|--------|------------|----|
| `sword_1` / `sword_2` / `sword_3` | 挥动主手且持剑 | 连击序列循环 | 5 tick | 1 |
| `punch_1` / `punch_2` | 挥动主手且空手 | 连击序列循环 | 5 tick | 1 |
| `break_right` | 挥动主手(持其他物品) | 单次播放 | 5 tick | -1 |
| `break_left` | 挥动副手 | 单次播放 | 5 tick | -1 |
| `bow_right` | 主手使用弓 | 单次播放 | 3 tick | -1 |
| `bow_left` | 副手使用弓 | 单次播放 | 3 tick | -1 |
| `crossbow_right` | 主手装填弩 / 持已装填的弩 | 单次播放 | 3 / 5 tick | -1 |
| `crossbow_left` | 副手装填弩 / 持已装填的弩 | 单次播放 | 3 / 5 tick | -1 |
| `trident_throw_right` | 主手投掷三叉戟 | 单次播放 | 3 tick | -1 |
| `trident_throw_left` | 副手投掷三叉戟 | 单次播放 | 3 tick | -1 |
| `shield_block_right` | 主手盾牌格挡 | 单次播放 | 3 tick | -1 |
| `shield_block_left` | 副手盾牌格挡 | 单次播放 | 3 tick | -1 |
| `eat_right` | 主手吃/喝 | 单次播放 | 3 tick | -1 |
| `eat_left` | 副手吃/喝 | 单次播放 | 3 tick | -1 |
| `spyglass_right` | 主手使用望远镜 | 单次播放 | 3 tick | -1 |
| `spyglass_left` | 副手使用望远镜 | 单次播放 | 3 tick | -1 |
| `toot_horn_right` | 主手使用山羊号角 | 单次播放 | 3 tick | -1 |
| `toot_horn_left` | 副手使用山羊号角 | 单次播放 | 3 tick | -1 |
| `brush_right` | 主手使用刷子 | 单次播放 | 3 tick | -1 |
| `brush_left` | 副手使用刷子 | 单次播放 | 3 tick | -1 |
| `use_right` | 主手使用物品(通用兜底) | 单次播放 | 3 tick | -1 |
| `use_left` | 副手使用物品(通用兜底) | 单次播放 | 3 tick | -1 |
| `empty` | 无手部动作(兜底) | 循环 | 500 tick | 1 |
- 带有 `_right` / `_left` 后缀的动画分别对应主手和副手操作。如果模型中未定义对应动画,则跳过该状态。
- `crossbow_right` / `crossbow_left` 在装填中过渡时间为 3 tick,持握已装填弩时为 5 tick。
- `empty` 的 500 tick 超长过渡时间用于从手部动作平滑回到无动作状态。
- 当服务端下发 AnimationCommand 时,副轨道会进入等待状态,将控制权交给主轨道。
## 第一人称物品动画名
用于第一人称视角下手持物品的动画,类似 FPS 游戏的武器动画系统。物品切换时会自动执行收起/拔出流程。
### 切换流程
1. 切换物品时,当前物品播放 `holster`(收起)动画
2. 收起完成后切换模型
3. 新物品播放 `draw`(拔出)动画
4. 拔出完成后进入默认状态循环
物品需要存在 `draw` 或 `idle` 动画之一,才会被识别为有效的第一人称物品模型。
### 动画名称
| 动画名 | 触发条件 | 播放方式 |
|-----------------------------------|-------------|-----------------|
| `holster` | 切换物品时收起当前物品 | 播放一次 |
| `draw` | 切换物品时拔出新物品 | 播放一次 |
| `sword_1` / `sword_2` / `sword_3` | 主手挥剑 | 连击序列,按 1→2→3 循环 |
| `run` | 移动中且冲刺(非潜行) | 循环 |
| `walk` | 行走(非潜行) | 循环 |
| `idle` | 兜底状态 | 循环 |
## 盔甲架状态动画名
盔甲架模型支持服务端下发的动画指令和默认待机动画。
| 动画名 | 触发条件 |
|---------|------------------------------|
| 服务端指令动画 | 通过 AnimationCommand 下发,优先级最高 |
| `idle` | 默认待机,循环播放 |
## 方块状态动画名
方块模型支持服务端下发的动画指令、距离触发动画和默认待机动画。优先级从高到低:
| 动画名 | 触发条件 |
|--------------|------------------------------|
| `closeTo_in` | 玩家进入方块设定距离范围时的过渡动画,播放一次 |
| `closeTo` | 玩家在方块设定距离范围内时,循环播放 |
| `idle` | 默认待机,循环播放 |
## 物品 / 展示物状态动画名
物品模型和展示物模型仅支持默认待机动画。
| 动画名 | 触发条件 |
|--------|-----------|
| `idle` | 默认待机,循环播放 |
---
## 模型定位器
URL: https://wiki.arcartx.com/docs/core/6_model/8_locator
## 手持物品定位器
生物模型被替换后,默认没有"手"的概念。通过基岩模型的定位器功能,可以告诉 ArcartX 手的位置,从而渲染手持物品。
在手部骨骼中创建定位器:
- 左手:`left_hand`
- 右手:`right_hand`
重载后即可在游戏中看到效果。如果位置不满意,调整定位器位置;如果旋转不满意,调整骨骼旋转。
## 鞘翅定位器
当玩家装备鞘翅时,ArcartX 可以在模型上渲染鞘翅。在模型的背部骨骼中创建名为 `elytra` 的定位器,ArcartX 会在该位置渲染鞘翅模型。
- 定位器名称:`elytra`
---
## Molang 查询
URL: https://wiki.arcartx.com/docs/core/6_model/9_molang
ArcartX 的模型动画系统支持 Molang 表达式,你可以在 Bedrock 动画文件的关键帧中使用以下查询变量来实现动态效果。
## 通用查询
以下查询适用于所有模型类型(实体、物品、方块、展示物等)。
| 查询 | 返回值 | 说明 |
|---------------------|-----------|-----------------------------------|
| `query.anim_time` | 秒 | 当前动画已播放的时间(秒),每个动画开始时重置为 0 |
| `query.life_time` | 秒 | 模型的存活时间(秒),从模型开始渲染时累计 |
| `query.actor_count` | 整数 | 当前世界中的实体总数 |
| `query.time_of_day` | 0.0 ~ 1.0 | 当前游戏内时间,0.0 为日出,0.5 为日落,1.0 为次日日出 |
| `query.moon_phase` | 0 ~ 7 | 当前月相,0 为满月,依次递增 |
## 实体查询
以下查询仅在实体模型上可用。
| 查询 | 返回值 | 说明 |
|------------------------------|-----------|--------------------------------------------|
| `query.distance_from_camera` | 浮点数 | 实体与摄像机之间的距离(方块数) |
| `query.is_on_ground` | 0.0 / 1.0 | 实体是否在地面上 |
| `query.is_in_water` | 0.0 / 1.0 | 实体是否在水中 |
| `query.is_in_water_or_rain` | 0.0 / 1.0 | 实体是否在水中或雨中 |
| `query.health` | 浮点数 | 实体当前生命值(仅 LivingEntity) |
| `query.max_health` | 浮点数 | 实体最大生命值(仅 LivingEntity) |
| `query.is_on_fire` | 0.0 / 1.0 | 实体是否着火(仅 LivingEntity) |
| `query.ground_speed` | 浮点数 | 实体水平方向移动速度,即 XZ 平面的速度分量合成值(仅 LivingEntity) |
| `query.yaw_speed` | 浮点数 | 实体视角水平旋转速度(仅 LivingEntity) |
## ArcartX 扩展查询
以 `ax.` 为前缀的查询是 ArcartX 的扩展变量,仅在实体模型上可用。
| 查询 | 返回值 | 说明 |
|---------------------|-----|--------------------------------------------|
| `ax.head_yaw` | 角度 | 实体头部的水平旋转角度(相对于身体) |
| `ax.head_pitch` | 角度 | 实体头部的俯仰角度 |
| `ax.move_forward` | 浮点数 | 前后移动输入值,正值为前进,负值为后退。本地玩家取键盘输入,其他实体取 AI 移动值 |
| `ax.move_strafe` | 浮点数 | 左右移动输入值,正值为左移,负值为右移。本地玩家取键盘输入,其他实体取 AI 移动值 |
| `ax.move_speed` | 浮点数 | 移动输入的合成速度,即 `sqrt(forward² + strafe²)` |
| `ax.vertical_speed` | 浮点数 | 实体垂直方向速度(Y 轴),正值为上升,负值为下降 |
布尔类型的查询(`is_on_ground`、`is_in_water` 等)返回 `1.0` 表示 true,`0.0` 表示 false,可直接用于数学运算。
---
## MythicMobs 额外词条
URL: https://wiki.arcartx.com/docs/core/7_mythicmobs/1_skill
## MythicMobs 额外词条
ArcartX 为 MythicMobs 提供了一系列自定义技能词条。以下是所有可用的词条及其参数说明。
每个参数都支持缩写和全名两种写法,例如 `m` 和 `model` 等价。
### 模型相关
```yaml
# 设置实体模型
# m(model): 模型 ID,为空则删除模型(默认 "")
# s(scale): 缩放大小(默认 1.0)
# r(reset): 是否重置上下文(默认 true)
# r 为 false 时不会更新模型上下文,适用于骨骼相同的模型动态切换而不中断动画
model{m=model_id; s=1; r=true} @self
```
```yaml
# 播放动画
# n(name): 动作名(默认 "idle")
# t(transitionTime): 过渡时长,单位 tick(默认 5)
# s(speed): 播放速度(默认 1.0)
# k(time): 持续时间,单位 tick,-1 为播放一次(默认 -1)
animation{n=idle; t=5; s=1; k=-1} @self
```
```yaml
# 隐藏骨骼
# b(bone): 骨骼名(默认 "head")
# h(hide): 是否隐藏(默认 true)
hideBone{b=head; h=true} @self
```
```yaml
# 设置动作替换
# s(state): 状态名(默认 "idle")
# a(animation): 替换为的动作名(默认 "idle")
defaultState{s=idle; a=idle2} @self
```
### 碰撞与代理
```yaml
# 设置碰撞体积
# w(width): 宽度(默认 1.0)
# h(height): 高度(默认 1.0)
hitbox{w=1; h=1} @self
```
```yaml
# 代理碰撞箱
# 生成一个隐形实体代替本体接受伤害,解决体积变大后寻路 AI 异常的问题
# 使用前需要先关闭本体的碰撞功能
# w(width): 宽度(默认 1.0)
# h(height): 高度(默认 1.0)
# u(update): 是否更新已存在的代理碰撞箱大小(默认 false)
# r(remove): 是否移除代理碰撞箱(默认 false)
hitboxProxy{w=10; h=10} @self
hitboxProxy{w=11; h=11; u=true} @self
hitboxProxy{r=true} @self
```
代理碰撞箱不会被 MythicMobs 范围技能选中(处理方式类似 MythicMobs 与 ModelEngine 的兼容)。在某些情况下,你可能需要对其它技能插件进行额外兼容。
### 坐骑系统
通过代理碰撞箱实现坐骑功能,支持船、地面生物、车辆、飞行、潜艇五种类型。
```yaml
# 设置坐骑类型
# t(type): 坐骑类型(默认 "NONE")
# 可选值: GROUND(地面) | FLY(飞行) | BOAT(船) | CAR(车辆) | DIVING(潜艇) | NONE(关闭)
proxyMountType{t=GROUND} @self
```
```yaml
# 设置坐骑速度
# s(moveSpeed): 移动速度(默认 0.3)
# fu(flyUpSpeed): 飞行上升速度(默认 0.08)
# fd(flyDownSpeed): 飞行下降速度(默认 0.06)
# bt(boatTurnSpeed): 船转向速度(默认 2.0)
proxyMountSpeed{s=0.3; fu=0.08; fd=0.06; bt=2.0} @self
```
```yaml
# 添加额外座位
# x/y/z: 座位相对于代理实体的偏移坐标(默认均为 0.0)
proxyAddSeat{x=0; y=0; z=1} @self
```
使用坐骑功能前,需要先通过 `hitboxProxy` 创建代理碰撞箱,再设置坐骑类型和速度。玩家右键代理实体即可上车。
### 音效与特效
```yaml
# 播放 3D 音效
# s(sound): 音频文件路径(默认 "null",即不播放)
# c(category): 音频类型(默认 "master")
# d(distOrRoll): 范围(默认 16)
# p(pitch): 音调(默认 1.0)
# k(keepTime): 持续时间,单位毫秒(默认 2000)
sound3d{s=sounds/hit.ogg; c=master; d=16; p=1; k=2000} @self
```
```yaml
# 在目标实体位置播放锤地特效(同步给可以看到该实体的玩家)
# r(radius): 半径(默认 3.0)
# d(depth): 深度(默认 0.3)
# i(in): 进入时间(默认 10)
# k(keep): 持续时间(默认 40)
# o(out): 退出时间(默认 20)
# m(mode): 动画类型 0|1|2(默认 0)
hammerEffect{r=3; d=0.3; i=10; k=40; o=20; m=0} @self
```
### UI 与相机
```yaml
# 向目标玩家发送 UI 通讯包,触发 UI 的 packetHandler
# u(ui): 界面 ID(默认 "")
# ph(packetHandler): 处理器名称(默认 "")
# pack/p: 包内容,字符串(默认 "")
uiPacket{u=my_ui; ph=handler_name; pack=data}
# 注意,这个要选择目标,而不是@self,@self是发给释放者
```
```yaml
# 摇晃目标镜头
# d(duration): 持续 tick(默认 20)
# a(amplitude): 幅度(默认 14)
cameraShake{d=20; a=14} @target
```
### 基岩粒子
```yaml
# 在目标实体位置播放基岩粒子
# id(pid): 粒子 ID(默认 "")
bedrockParticle{id=magic}
```
## 自定义词条名称
如果你使用的其它插件和 ArcartX 的词条名称冲突,可以在 `plugins/ArcartX/link/mythicmobs_key_words.yml` 中修改词条名称。
修改词条名称后需要重启服务端才会生效。
如果你从旧版本升级,原来位于 `mythicmobs/key_words.yml` 的配置文件会自动迁移到 `link/mythicmobs_key_words.yml`。
---
## MythicMobs 额外配置项
URL: https://wiki.arcartx.com/docs/core/7_mythicmobs/2_config
## MythicMobs 额外配置
ArcartX 为 MythicMobs 的生物配置提供了以下额外字段,可以直接写在 MythicMobs 的 mob 配置中:
```yaml
test:
Type: ZOMBIE
Display: '&a示例'
Health: 1
Model: "test" # 模型 ID,等效于使用 model 技能词条
Scale: 0.5 # 模型缩放
HideName: true # 隐藏名称标签,适用于陷阱类生物
HideHitBox: true # 隐藏碰撞箱渲染,适用于遁地或隐身怪物
```
| 配置项 | 类型 | 说明 |
|:---|:---:|:---|
| Model | string | 模型 ID,生物生成时自动设置模型 |
| Scale | double | 模型缩放比例 |
| HideName | boolean | 是否隐藏名称标签 |
| HideHitBox | boolean | 是否隐藏碰撞箱的客户端渲染 |
---
## MythicMobs 额外投掷物
URL: https://wiki.arcartx.com/docs/core/7_mythicmobs/3_ammo
## 模型投掷物
对于某些投掷物,你可能希望它以自定义模型的外观显示。ArcartX 提供了 `model` 类型的投掷物弹道来实现这一需求。
由于 MythicMobs 没有注册投掷物的接口,模型投掷物是通过反射注册的,不一定所有 MythicMobs 版本通用。
### 参数说明
在 `projectile` 技能中,设置 `bullet=model` 即可启用模型投掷物,额外参数如下:
| 参数 | 全名 | 类型 | 默认值 | 说明 |
|:---|:---|:---:|:---:|:---|
| mid | modelID | string | "" | 模型 ID |
| s | scale | double | 1.0 | 模型缩放 |
### 示例
```yaml
示例模型子弹:
Conditions:
Skills:
- projectile{
v=5;
i=1;
hR=0.5;
vR=0.5;
Maxduration=200;
MaxRange=99;
hnp=true;
hp=false;
hO=0;
sE=false;
sB=true;
hs=false;
hfs=0;
syo=1.5;
tyo=1.5;
bullet=model;
mid=test;
s=1;
onEnd=[
];
onHit=[
];
onBounceSkill=[
]} @Forward{f=15;y=0}
```
配置方式与普通投掷物一致,只需将 `bullet` 设为 `model`,并通过 `mid` 和 `s` 指定模型 ID 和缩放。
---
## 控件变量以及函数
URL: https://wiki.arcartx.com/docs/core/8_ui/10_controls_shimmer
## 控件变量以及函数
- 这里列出控件中可用的Shimmer函数以及控件对象自身的变量。
## 变量
### 固有变量
- `type` 控件类型(固定值无法修改)
- `actions` 触发器字典[字典类型]
- `dragX` 当前X轴被拖动距离[数字类型](可赋值,但是应当是数字类型)
- `dragY` 当前Y轴被拖动距离[数字类型](可赋值,但是应当是数字类型)
- `meta` 元数据[字典类型]
### 动态变量
- 我记得在控件结构中提到了,属性是可以自己命名创建的。
- 比如下面这个配置:
```yaml
background:
type: texture
attribute:
point: ~middle_center
width: 1000
height: 500
normal: ~AXLoginView/background.png
abcd: "~我是一条自定义属性"
```
- 这个时候这个控件可访问的变量包含`attribute`块下所有的值。
- 也就是`abcd`这个值,可以通过`self.abcd{:Shimmer}`来访问或赋值。
- 其余变量同理,比如`width` 可以通过`self.width{:Shimmer}`来访问或赋值。
- 当然,没有在这个块里面声明的值也可以赋值访问,比如`self.a = 10{:Shimmer}`
## 元素
- 通过控件对象自身,可通过元素访问语法来获取子级控件对象
- 比如我们获取子级的`button`控件,则可以用`self['button']{:Shimmer}`来访问。
## 函数
### `parent(){:Shimmer}`
- 获取控件父级(如果是顶层控件返回的是UI对象)
- **参数**:无
- **返回值**:UI 或 控件
- **调用示例**
```Shimmer
self.parent()
```
### `childrenCount(){:Shimmer}`
- 获取子级控件数量(仅限子级,孙级以及以上不包含)
- **参数**:无
- **返回值**:数字类型
- **调用示例**
```Shimmer
self.childrenCount()
```
### `remove(){:Shimmer}`
- 移除当前控件
- 该语句不应在进行copy操作后立即调用
- **参数**:无
- **返回值**:无
- **调用示例**
```Shimmer
self.remove()
```
### `setDragXRatio(value){:Shimmer}`
- 设置X轴拖动比率
- **参数**:`value`(比率,数字类型)
- **返回值**:无
- **调用示例**
```Shimmer
self.setDragXRatio(0.5)
```
### `setDragYRatio(value){:Shimmer}`
- 设置Y轴拖动比率
- **参数**:`value`(比率,数字类型)
- **返回值**:无
- **调用示例**
```Shimmer
self.setDragYRatio(0.5)
```
### `getDragXRatio(){:Shimmer}`
- 获取X轴拖动比率
- **参数**:无
- **返回值**:数字类型
- **调用示例**
```Shimmer
self.getDragXRatio()
```
### `getDragYRatio(){:Shimmer}`
- 获取Y轴拖动比率
- **参数**:无
- **返回值**:数字类型
- **调用示例**
```Shimmer
self.getDragYRatio()
```
### `copy(name){:Shimmer}`
- 复制当前控件,并命名为`name`,调用后即刻添加至当前层级中
- **参数**:`name`(复制后的控件名称,字符串类型)
- **返回值**:控件对象
- **调用示例**
```Shimmer
self.copy("newControl")
```
### `clear(){:Shimmer}`
- 清除当前控件的所有子级控件
- **参数**:无
- **返回值**:无
- **调用示例**
```Shimmer
self.clear()
```
### `getStackWidth(){:Shimmer}`
- 获取当前控件的堆叠宽度(仅限HStack)
- **参数**:无
- **返回值**:数字类型
- **调用示例**
```Shimmer
self.getStackWidth()
```
### `getStackHeight(){:Shimmer}`
- 获取当前控件的堆叠高度(仅限VStack)
- **参数**:无
- **返回值**:数字类型
- **调用示例**
```Shimmer
self.getStackHeight()
```
### `getSlotItemStack(){:Shimmer}`
- 获取当前控件的物品(仅限Slot)
- **参数**:无
- **返回值**:物品对象
- **调用示例**
```Shimmer
self.getSlotItemStack()
```
### `getItemValueSum(key){:Shimmer}`
- 获取整个UI中和当前控件中物品相同的槽位的物品量总和(当前控件数量不计入其中)用于做图纸插件的UI显示材料(仅限Slot)
- **参数**:`key`(物品键,字符串类型)
- **返回值**:数字类型
- **调用示例**
```Shimmer
self.getItemValueSum("exampleKey")
```
### `getItemText(key){:Shimmer}`
- 获取当前控件的物品文本值,比如有一行lore是`xxx: abc`,该函数用于获取冒号后面的内容(仅限Slot)
- **参数**:`key`(键内容,字符串类型)
- **返回值**:字符串类型
- **调用示例**
```Shimmer
self.getItemText("exampleKey")
```
### `setContent(content){:Shimmer}`
- 设置文本框的内容(仅限TextBox | ChatTextBox)
- **参数**:`content`(内容,字符串类型)
- **返回值**:无
- **调用示例**
```Shimmer
self.setContent("exampleContent")
```
### `getContent(){:Shimmer}`
- 获取文本框的内容(仅限TextBox | ChatTextBox)
- **参数**:无
- **返回值**:字符串类型
- **调用示例**
```Shimmer
self.getContent()
```
### `insert(text){:Shimmer}`
- 在当前指针位置插入文字(仅限TextBox | ChatTextBox)
- **参数**:`test`(插入的内容,字符串类型)
- **返回值**:无
- **调用示例**
```Shimmer
self.insert("exampleText")
```
### `setFocus(value){:Shimmer}`
- 设置当前控件是否获取焦点(仅限TextBox | ChatTextBox)
- **参数**:`value`(布尔类型,true表示获取焦点,false表示失去焦点)
- **返回值**:无
- **调用示例**
```Shimmer
self.setFocus(true)
```
### `isHovered(){:Shimmer}`
- 获取控件此时是否鼠标悬停
- **参数**:无
- **返回值**:布尔类型
- **调用示例**
```Shimmer
self.isHovered()
```
### `setItemIcon(item){:Shimmer}`
- 设置控件的图标物品(仅限Slot 且类型为Icon)
- **参数**:`item`(物品JSON,字符串类型, 这个值需要序列化物品发送)
- **返回值**:无
- **调用示例**
```Shimmer
self.setItemIcon('{"id": "minecraft:stone","Count":1}')
```
### `getSameCount(){:Shimmer}`
- 获取当前容器中,有多少和当前Slot相同的物品数量(仅限Slot)
- **参数**:无
- **返回值**:数字类型
- **调用示例**
```Shimmer
self.getSameCount()
```
### `needShowAll(){:Shimmer}`
- 获取聊天栏控件此时是否需要全部展示(仅限ChatTextBox)
- **参数**:无
- **返回值**:布尔类型
- **调用示例**
```Shimmer
self.needShowAll()
```
### `getVisibleChildren(){:Shimmer}`
- 获取当前控件下所有可见子控件,不包含孙控件
- **参数**:无
- **返回值**:列表
- **调用示例**
```Shimmer
self.getVisibleChildren()
```
### `create(){:Shimmer}`
- 在当前控件层级通过模板创建控件
- **参数**:`tempID` 模板ID、 `newName` 新创建控件的ID
- **返回值**:无
- **调用示例**
```Shimmer
self.create('模板ID', '新控件ID')
```
- **示例返回值**
```Shimmer
// 返回一个控件对象
```
- 和界面的一级创建控件差不多,这个是在当前控件层级创建子控件。
### `send(){:Shimmer}`
- 发送聊天栏输入框的内容(仅限 ChatBox 控件)
- **参数**:无
- **返回值**:无
- **调用示例**
```Shimmer
self.send()
```
### `get(index){:Shimmer}`
- 通过索引获取子控件
- **参数**:`index`(子控件索引,数字类型)
- **返回值**:控件对象
- **调用示例**
```Shimmer
self.get(0)
```
### `replay(){:Shimmer}`
- 重新播放gif(仅限TextView)
- **参数**:无
- **返回值**:无
- **调用示例**
```Shimmer
self.replay()
```
---
## 尝试编写一个UI
URL: https://wiki.arcartx.com/docs/core/8_ui/11_try
## 尝试编写一个UI
- 接下来通过一个实际案例来学习 UI 编写。下面将创建一个替换原版生存模式背包的 UI。
### 1.资源文件准备
- 首先准备好我们的资源文件
### 2.创建UI配置文件
- 在服务端创建UI配置文件
### 3.编写UI配置文件
- 设置UI属性,这里其余属性都用默认值就行了,只需要配置`match`,在替换匹配里加一个原版背包界面的ID
```yaml
ui:
match:
- 物品栏界面
```
- 保存,重载,这个时候重载然后打开背包已经可以发现啥也没有了,因为我们还没有创建控件内容,这个时候打开背包发现是空的说明操作正确
### 4.编写基础控件
- 然后我们开始创建控件,我们将所有组件放在自适配布局控件下,这样就省的根据窗口大小做适配了
```yaml
ui:
match:
- 物品栏界面
controls:
adaptive:
type: adaptive
attribute:
point: ~middle_center
width: 1920
height: 1080
```
- 继续往下写,我们把背景图控件加上
```yaml
ui:
match:
- 物品栏界面
controls:
adaptive:
type: adaptive
attribute:
point: ~middle_center
width: 1920
height: 1080
children:
background:
type: Texture
attribute:
point: ~middle_center
width: 1270
height: 650
normal: ~inventory/bg.png
```
- 然后保存重载,就可以看到背景已经渲染了
- 再然后顺便把实体也塞进去
```yaml
# 上文省略
player:
type: Entity
attribute:
x: 200
y: 60
scale: 5
hideTag: true
followMouse: true
```
- 基本可以说是初见端倪,接下来做物品栏位。既然有脚本支持,就不需要手动创建几十个槽位了。
- 这里我们利用网格布局控件来帮助我们排列槽位控件的位置,并且使用语句复制槽位并设置槽位id
```yaml
# 上文省略
slots:
type: Grid
attribute:
x: 420
y: 60
spaceBetweenY: 60
spaceBetweenX: 10
column: 9
action:
create: |-
// 创建背包栏位的槽位
for(i in range(1,26)){
slot = self['slot0'].copy('slot' + i)
slot.id = 9 + i
}
children:
slot0:
type: slot
attribute:
width: 80
height: 80
normal: ~inventory/item.png
hover: ~inventory/item_.png
itemScale: 0.5
id: 9
```
- 基本上可以看到背包的雏形, 下面的快捷栏槽位也是以此类推,不过用的是横向布局控件。
- 如此便是基本完成了一个背包 UI。护甲和副手槽位的写法类似,这里不再重复。
- 来看看完整配置内容
```yaml
ui:
match:
- 物品栏界面
controls:
adaptive:
type: adaptive
attribute:
point: ~middle_center
width: 1920
height: 1080
children:
background:
type: Texture
attribute:
point: ~middle_center
width: 1270
height: 650
normal: ~inventory/bg.png
children:
player:
type: Entity
attribute:
x: 200
y: 60
scale: 5
hideTag: true
followMouse: true
slots:
type: Grid
attribute:
x: 420
y: 60
spaceBetweenY: 60
spaceBetweenX: 10
column: 9
action:
create: |-
// 创建背包栏位的槽位
for(i in range(1,26)){
slot = self['slot0'].copy('slot' + i)
slot.id = 9 + i
}
children:
slot0:
type: slot
attribute:
width: 80
height: 80
normal: ~inventory/item.png
hover: ~inventory/item_.png
itemScale: 0.5
id: 9
hot_slots:
type: HStack
attribute:
x: 100
y: 530
spaceBetween: 40
action:
create: |-
for(i in range(1,8)){
slot = self['slot0'].copy('slot' + i)
slot.id = 36 + i
}
children:
slot0:
type: slot
attribute:
width: 80
height: 80
normal: ~inventory/item.png
hover: ~inventory/item_.png
itemScale: 0.5
id: 36
```
- UI 部分的教程到此结束。虽然涵盖了 11 个章节,但多上手实践并不难。
- 多尝试几次就能熟练掌握。
---
## BossBar使用说明
URL: https://wiki.arcartx.com/docs/core/8_ui/12_bossbar
## BossBar 使用说明
- Bossbar的配置格式和UI差不多,但是Bossbar是属于"零散的UI",它是通过`BossBars`控件自动创建到UI中,而不是直接在UI中创建的。
- 如果你跳过了前面的UI教学,*请不要尝试强行理解该章节*。
- 本章节涉及两个控件: BossBars 和 BossBar,具体说明请查看本篇的控件类型。
## 简单示例
- Bossbar的配置位于ArcartX配置目录下的`boss_bar`文件夹,你可以创建多个BossBar配置。
```yaml
bossbar:
match:
- "boss" # 填写匹配生物名,不需要填写颜色代码。建议生物名匹配时添加特殊符号(如果你不希望玩家也被匹配到),因为匹配时不包含颜色代码
root_control: # 填写控件片段,注意,如果你的载体BossBars控件已经使用了自适应布局控件作为父级,这里不需要再套一层
type: canvas
attribute:
width: 1000
height: 60
children:
name:
type: text
attribute:
center: true
x: 500
y: 5
fontSize: 32
texts: self.parent.entityName # 生物名会作为变量加入到该血条的根控件中
bar:
type: bossbar
attribute:
width: 1000
height: 20
y: 30
textures: # 这里填写每层的贴图 填多少个就会分为多少层
- ~255,0,0
- ~0,255,0
- ~0,0,255
```
- 随后一切都由 ArcartX *自行处理*。
- 当玩家交互/攻击实体时,匹配到生物名,ArcartX 会在所有正在渲染的 UI 中的 BossBars 控件中自动创建血条控件,在实体死亡或从世界移除后将会删除。
- 你只需要在 UI 中创建一个 BossBars 控件即可。下面提供一个 UI 示例,你可以把这个复制到 ui 目录,然后把上面的复制到 boss_bars 目录,生成一个名为 boss 的实体,然后攻击该实体即可看到效果。
```yaml
ui:
isHud: true
controls:
adaptive:
type: adaptive
attribute:
point: ~top_center
width: 1920
height: 1080
children:
bossBars:
type: bossBars
attribute:
point: ~top_center
```
---
## 自定义聊天栏
URL: https://wiki.arcartx.com/docs/core/8_ui/13_chat
## 自定义聊天栏
- ArcartX 的 UI 控件提供了聊天栏所需的所有功能,你可以通过 UI 控件来实现自定义聊天栏。
- 此外,使用ArcartX替换原版聊天栏,还可支持额外的卡片消息、特殊颜色、表情符号等功能。
## 一个简单的聊天栏配置
- 涉及聊天栏的控件有 `ChatTextBox`(聊天栏输入框) `Chat`(聊天栏) `Suggestion`(命令补全)
- 下面是一个简单的聊天栏配置示例:
- 第一部分是聊天栏的HUD部分
```yaml
ui:
isHud: true
hide:
- chat_panel # 隐藏原版聊天栏
controls:
adaptive:
type: adaptive
attribute:
point: ~bottom_left
width: 1920
height: 1080
children:
chat:
type: chat
attribute:
width: 700
height: 400
point: ~bottom_left
background: ~0,0,0,80
fontSize: 28
y: -280
x: 35
```
- 第二部分是替换原版聊天栏输入框界面
```yaml
ui:
match:
- ChatScreen # 匹配原版聊天界面
background: false
# 这俩记得打开,不然交互不了HUD
transfer: true # 传递交互
through: true # 穿透
controls:
adaptive:
type: adaptive
attribute:
point: ~bottom_left
width: 1920
height: 1080
children:
background:
type: texture
attribute:
point: ~bottom_left
width: 700
height: 24
x: 35
y: -250
normal: ~0,0,0,80
input:
type: chatTextBox
val: input
attribute:
point: ~bottom_left
length: 64
x: 75
y: -250
fontSize: 28
width: 615
height: 20
action:
create: |-
self.setFocus(true)
children:
suggestion:
type: Suggestion
attribute:
fontSize: 28
background: ~0,0,0,80
```
- 直接复制粘贴创建配置,即可看到效果:
- 该聊天栏支持特殊颜色和表情符号:
## 卡片消息
- 卡片消息可用于在聊天栏中展示好友请求、组队邀请、红包等交互式内容。
- 它是将一个控件加入到聊天栏。注意,聊天栏最多存储 10 个卡片消息,超出 10 个会将最早创建的卡片消息显示为"卡片消息已失效"。
- 效果:
- 卡片消息本质上就是一个控件,因此你可以使用背景、按钮、文本等控件来构建自定义的卡片消息。
- 它的配置位于插件的 `chat_card` 文件夹,你可以创建多个卡片消息模板。
``` yaml
root_control:
type: card # 注意这里必须是card类型
attribute:
width: 20 # 填写正确的尺寸以便聊天栏控件排列
height: 50 # 如果你的聊天栏本身已经套了一层自适应布局控件,这里不需要再套一层
children:
texture:
type: texture
attribute:
width: 500
height: 50
normal: ~255,0,0
hover: ~255,255,0
texts: "'我是一个卡片消息' + self.parent.data['name']"
fontSize: 32
action:
click: |-
Message.chat('点我干嘛')
```
- 卡片消息需要使用API发送,每个卡片消息可以附带一个 `Map` 数据,正如上面示例配置的这一行`'我是一个卡片消息' + self.parent.data['name']{:Shimmer}`,它会将数据中的`name`值渲染到文本中。
- 发送卡片消息的API如下:
- Kotlin
```kotlin
// 卡片消息配置路径:例如配置位于ArcartX/chat_card/example.yml 此处填写example 如果位于子文件夹使用斜杠分割
player.arcartXHandler?.sendChatCard("卡片消息配置路径", mapOf("name" to player.name))
```
- Java
```java
// 卡片消息配置路径:例如配置位于ArcartX/chat_card/example.yml 此处填写example 如果位于子文件夹使用斜杠分割
ArcartXPlayer arcartXPlayer = PlayerUtils.getArcartXHandler(player);
if(arcartXPlayer != null){
arcartXPlayer.sendChatCard("卡片消息配置路径", Map.of("name",player.getName()));
}
```
---
## UI定时任务
URL: https://wiki.arcartx.com/docs/core/8_ui/14_task
## UI 定时任务
UI 定时任务用于在指定时间执行脚本,或按设定的周期循环执行脚本,适用于需要根据生命周期来执行的逻辑。
配置格式如下:
```yaml
ui:
match:
- ChatScreen
background: false
through: true
tasks:
测试延迟:
type: delay
time: 5000
run: |-
Message.chat("测试延迟任务")
测试循环:
type: loop
time: 3000
cycle: 1000
run: |-
Message.chat("测试循环任务")
```
---
## 开始
URL: https://wiki.arcartx.com/docs/core/8_ui/1_start
## 前言
- 学习 UI 之前,请先学习 Shimmer 的使用,UI 的中后期应用是围绕脚本展开的。
- 如果你只需要制作简单的 UI,且运算仅涉及基础的数字加减乘除,可以跳过 Shimmer 部分。
- UI 的讲解中会穿插部分开发相关内容,请根据需要自行参考。
- 以下是一条重要提示,请务必留意。
- UI 几乎所有属性都是脚本语句,因此如果某个属性的值是字符串,无法直接作为文本读取。
- 因为 Shimmer 的字符串使用单引号包裹,比如`"abc"{:Shimmer}`,而 YAML 语法中引号涉及转义问题。
- 所以,如果某个属性你想设定为纯文字,只需要在开头加上一个`~`即可。
- 比如`texts: "~我是一个纯文字属性值"{:yaml}`
- 对于 UI 系列内容,HUD 和 Menu 使用同一个配置文件,位于同一个文件夹。如果你是直接在 ArcartX 的 ui 目录下创建的 UI 配置,那么 UI 的 id 即为文件名本身。
- 比如`xxx.yml`对应的 id 就是`xxx`,如果是`xxx/yyy.yml`,那么 id 就是`xxx/yyy`。
- 如果你是附属开发者,建议注册 UI 时遵循以下格式:`插件名:ID`,例如`ArcartXAuthmeView:Main`
## UI的上下文逻辑
- 在学习完 Shimmer 之后,下面简单讲解一下 UI 的上下文逻辑。
- 我们先看一下UI的整体配置,这里放置了一个组件做示例
```yaml
ui:
match:
hide: []
itemSize: "16"
through: "false"
escClose: "true"
background: true
closeDied: "true"
show: "true"
jei: "false"
action:
controls:
background:
type: "Texture"
attribute:
width: "1270"
height: "650"
normal: "~inventory/bg.png"
template:
我是一个模板:
type: "Texture"
attribute:
width: "128"
height: "128"
normal: "~inventory/xxx.png"
```
- 不难看出 UI的配置分为两个大板块,一个是`ui`,一个是`controls`
- 在Shimmer教学中我们提到过载体关键字:`self`,这里讲解一下不同位置的`self`所指向的对象。
- 在`ui`这个配置项以内,所有的`self`关键字指向的是ui自身。
- 在`controls`这个配置项以内,所有的`self`关键字指向的是当前组件。
- 此外,UI 作为一个整体,共享同一个本地变量池(`var`、`val`),也就是你在`ui`块创建的本地变量,在控件中也可引用,反之亦然。
- 对于`template`块,写法和`controls`一模一样,但是这个块中的控件是作为模板存在,不会被创建,需要主动使用create函数来加入到UI中。用于动态创建UI的需求(后续请看UI的Shimmer函数和控件的Shimmer函数)
---
## UI 属性
URL: https://wiki.arcartx.com/docs/core/8_ui/2_ui_attribute
## UI 属性
UI 分为两种类型:
- `Menu` — 打开后会弹出鼠标光标的界面(如背包、商店等)
- `HUD` — 常驻于屏幕上的界面(如血条、状态栏等)
两种类型共用同一套配置,但部分属性仅对特定类型生效。不需要更改默认值的属性可以省略不写。
```yaml
ui:
match: []
hide: []
itemSize: "16"
through: "false"
escClose: "true"
background: "true"
closeDied: "true"
show: "true"
jei: "false"
level: "0"
screenScale: true
isHud: "false"
defaultOpen: "true"
action: # 详见 UI 触发器章节
packetHandler: # 详见 UI 通讯章节
```
### 属性详解
**match**
- **脚本支持:** 否
- **生效对象:** Menu 类型
- **默认值:** 无
- **说明:** 用于替换原版界面。填写原版界面 ID,当玩家打开对应的原版界面时,会自动替换为你的自定义 UI。
- 如何获取原版界面 ID:打开客户端日志,每次打开一个界面都会输出对应的 ID。
- 支持正则匹配:开头使用 `[regex]` 即代表正则匹配,例如 `[regex].*Chest.*{:yaml}`
- 注意:ArcartX 内置了友好名称字典(中文),这是因为Fabric使用了中介名,难以理解含义。旧版教程中可能仍使用原始类名(英文),请分辨并替换为最新写法。
- 容器的匹配不包含颜色符号。
**hide**
- **脚本支持:** 否
- **生效对象:** Menu 类型、HUD 类型
- **默认值:** 无
- **说明:** 当此 UI 存在时,隐藏指定的 HUD。ArcartX 自定义 HUD 填写对应 ID,原版 HUD 名称如下:
- `vignette` `spyglass` `helmet` `frostbite` `portal` `hotbar` `crosshair`
- `boss_event_progress` `player_health` `armor_level` `food_level` `air_level`
- `mount_health` `jump_bar` `experience_bar` `item_name` `sleep_fade`
- `potion_icons` `debug_text` `fps_graph` `record_overlay` `title_text` `subtitles`
- `scoreboard` `chat_panel` `player_list`
- `recipe_toast` `system_toast` `advancement_toast` `tutorial_toast`(右上角弹出消息)
- 1.20.1 以上版本:`player_state`(对应 player_health / armor_level / food_level / air_level 的合集)
**itemSize**
- **脚本支持:** 是
- **生效对象:** Menu 类型
- **默认值:** 16
- **说明:** 点击槽位拿起物品后,鼠标指针上渲染的物品图标大小。
**through**
- **脚本支持:** 是
- **生效对象:** Menu 类型、HUD 类型
- **默认值:** false
- **说明:** 是否开启穿透点击。为 true 时,重叠的组件会同时触发点击事件;为 false 时只触发最上层组件的事件。
**escClose**
- **脚本支持:** 是
- **生效对象:** Menu 类型
- **默认值:** true
- **说明:** 是否允许按 ESC 关闭此 UI。
**background**
- **脚本支持:** 是
- **生效对象:** Menu 类型
- **默认值:** true
- **说明:** 是否渲染半透明黑色背景(原版打开 UI 时的背景遮罩)。
**closeDied**
- **脚本支持:** 是
- **生效对象:** Menu 类型
- **默认值:** true
- **说明:** 玩家死亡时是否关闭此 UI。如果你替换的是原版死亡界面,需要设为 false。
**show**
- **脚本支持:** 是
- **生效对象:** Menu 类型、HUD 类型
- **默认值:** true
- **说明:** UI 是否渲染显示。
**jei**
- **脚本支持:** 是
- **生效对象:** Menu 类型
- **默认值:** false
- **说明:** 打开此 UI 时是否渲染 JEI 侧边栏。
**level**
- **脚本支持:** 是
- **生效对象:** HUD 类型
- **默认值:** 0
- **说明:** HUD 渲染优先级。数字越大越先渲染(显示在越底层)。
**isHud**
- **脚本支持:** 否
- **生效对象:** HUD 类型
- **默认值:** false
- **说明:** 是否作为 HUD 类型。设为 true 后此 UI 将作为常驻 HUD 显示。
**defaultOpen**
- **脚本支持:** 否
- **生效对象:** HUD 类型
- **默认值:** true
- **说明:** HUD 加载后是否立即打开。设为 false 时需要通过指令 `/a screen open` 或 API 手动控制。
**screenScale**
- **脚本支持:** 否
- **生效对象:** Menu 类型、HUD 类型
- **默认值:** true
- **说明:** 是否启用屏幕缩放适配。
---
## UI触发器
URL: https://wiki.arcartx.com/docs/core/8_ui/3_ui_action
## UI触发器
- 以下是 UI 支持的所有触发器:
| 名称 | 说明 | 备注 |
|:-------------:|:------:|:-------------------------------------------------:|
| keyPress | 键盘按下 | 通过`self.currentKeyPress{:Shimmer}`获取按下的按键 |
| keyRelease | 键盘释放 | 通过`self.currentKeyReleased{:Shimmer}`获取释放的按键 |
| wheel | 滚轮 | 通过`self.wheelValue{:Shimmer}`可通过正负判断滚动方向 |
| message | 接收消息 | 通过`Chat.getEventMessage(){:Shimmer}`获取本次触发事件的消息内容 |
| chatOpen | 聊天框打开 | |
| chatClose | 聊天框关闭 | |
| open | 打开 | 该触发器触发于UI所有控件初始化之后 |
| click | 点击 | |
| clickLeft | 左键点击 | |
| clickRight | 右键点击 | |
| clickMiddle | 中键点击 | |
| release | 释放 | |
| releaseLeft | 左键释放 | |
| releaseRight | 右键释放 | |
| releaseMiddle | 中键释放 | |
| resize | 游戏尺寸变化 | |
| close | 关闭 | |
| tick | 逻辑帧 | 正常来说是每秒触发100次,和渲染帧不一样,运算层和逻辑层是分开的 |
| seconds | 每秒 | 每秒触发一次,用于一些需要低频循环调用的逻辑 |
| load | 读取 | UI自身加载完成后触发,和open不同的是该触发器触发于UI控件初始化之前 |
触发器会在指定的时机执行对应的脚本语句,例如在点击时给玩家发送一条聊天消息。
---
## UI通讯处理
URL: https://wiki.arcartx.com/docs/core/8_ui/4_ui_packet
## UI通讯处理
- 这里其实算是一个开发文档,如果你不涉及写插件应该用不到这个,不过,某些情况你可能需要修改你所使用插件的UI的一些逻辑,可能也需要对本章进行了解。
- 先上一个包含通讯处理的UI配置
```yaml
ui:
packetHandler:
init: |-
var.title = packet['title']
val.inputs.actions['init'](packet['type'])
val.button.actions['init'](packet['type'])
result: |-
var.title = packet
close: |-
async {
Thread.sleep(500)
self.close()
}
```
- 当服务端使用API对指定UI发包的时候,会触发对应ID的包处理器。
- 用上面这个配置举例,比如我要触发init这个处理器的逻辑,则服务端对应的代码应该是这样的
```java
ui.sendPacket(player,"init", Map.of("type","register","title","你好"));
```
- 这里的`init`就是上面配置中的`init`,而`Map.of("type","register","title","你好"){:java}`就是传递给处理器的包内容。
- 值得注意的是,包内容只允许是基本数据类型以及List和Map,且如果是集合类型,其内容也应是基本数据类型或者只包含基本数据类型的集合。
- 在服务端运行上述代码发送包到这个UI的时候,便会执行相对应的脚本。
- 从示例不难看出,发来的包的内容会赋值给变量`packet`,你可以通过脚本进行读取并执行你的逻辑。
UI 发包带有缓存机制:如果目标 UI 尚未打开,发送的包会被临时缓存,在 UI 打开后自动处理。不过,预先发送的包无法访问控件数据,因为它触发于控件创建之前。
---
## UI变量以及函数
URL: https://wiki.arcartx.com/docs/core/8_ui/5_ui_shimmer
## UI变量以及函数
- 这里列出UI中可用的Shimmer函数以及UI对象自身的变量。
## 元素
- 通过ui对象自身,可通过元素访问语法来获取顶层控件对象
- 比如我们获取顶层的`background`控件,则可以用`self['background']{:Shimmer}`来访问。
## 变量
- `itemSize` 物品大小(MENU类型含有)
- `through` 是否穿透(MENU类型、HUD类型含有)
- `escClose` 是否按ESC关闭(MENU类型含有)
- `background` 背景颜色(MENU类型含有)
- `closeDied` 是否关闭时死亡(MENU类型含有)
- `show` 是否显示(MENU类型、HUD类型含有)
- `jei` 是否显示JEI(MENU类型含有)
- `actions` 触发器字典[字典类型](MENU类型、HUD类型含有)
- `wheelValue` 滚轮值(MENU类型、HUD类型含有)
- `currentKeyPress` 当前按键按下(MENU类型、HUD类型含有)
- `currentKeyReleased` 当前按键释放(MENU类型、HUD类型含有)
- `level` 渲染优先级(HUD类型含有)
## 函数
### `childrenCount(){:Shimmer}`
- 获取顶层组件数量
- **参数**:无
- **返回值**:数字类型
- **调用示例**
```Shimmer
self.childrenCount()
```
- **示例返回值**
```Shimmer
1
```
### `close(){:Shimmer}`
- 关闭当前UI
- **参数**:无
- **返回值**:无
- **调用示例**
```Shimmer
self.close()
```
- **示例返回值**
```Shimmer
无
```
### `getID(){:Shimmer}`
- 获取当前UI的ID
- **参数**:无
- **返回值**:字符串类型
- **调用示例**
```Shimmer
self.getID()
```
- **示例返回值**
```Shimmer
"exampleUI"
```
### `removeControlWithMeta(){:Shimmer}`
- 匹配控件元数据删除控件
- 关于控件meta的操作直接举例似乎不太直观,这里详细说明一下。
- 对于控件有一个固有常量:`meta` 调用方式是`val.控件.meta{:Shimmer}`
- 其储存一个字典型数据,你可以在触发器中去写入元数据键值对。
- **参数**:`key` (元数据键)和`value`(元数据值,可选,如果不包含值则只要包含键即符合匹配)
- **返回值**:无
- **调用示例**
```Shimmer
self.removeControlWithMeta("exampleKey", "exampleValue")
```
- **示例返回值**
```Shimmer
无
```
### `getControlWithMeta(){:Shimmer}`
- 匹配控件元数据获取控件
- 关于控件meta的操作直接举例似乎不太直观,这里详细说明一下。
- 对于控件有一个固有常量:`meta` 调用方式是`val.控件.meta{:Shimmer}`
- 其储存一个字典型数据,你可以在触发器中去写入元数据键值对。
- **参数**:`key` (元数据键)和`value`(元数据值,可选,如果不包含值则只要包含键即符合匹配)
- **返回值**:列表
- **调用示例**
```Shimmer
self.getControlWithMeta("exampleKey", "exampleValue")
```
- **示例返回值**
```Shimmer
[控件对象A,控件对象B...]
```
### `getSlotItemStack(){:Shimmer}`
- 获取指定槽位的物品
- **参数**:`slotName` (槽位ID)和`slotType`(槽位类型)
- **返回值**:物品堆
- **调用示例**
```Shimmer
self.getSlotItemStack('xxx', "Extra")
```
- **示例返回值**
```Shimmer
// 会返回一个物品对象,如果为空会返回空气
```
### `getOriginalName(){:Shimmer}`
- 仅Menu类型包含
- 获取UI的原始名称(如果该UI是作为替换原版UI渲染的)
- **参数**:无
- **返回值**:字符串类型
- **调用示例**
```Shimmer
self.getOriginalName()
```
- **示例返回值**
```Shimmer
"原版UI名称"
```
### `clickSlot(){:Shimmer}`
- 仅Menu类型包含
- 模拟点击容器槽位,比如你替换了原版的箱子菜单,可以模拟点击对应槽位触发原版的点击槽位事件。
- **参数**:`id` (槽位ID)、`button`(按键id,一般为0、1、2) 和`type`(点击类型,可选,默认为"PICKUP")
- **可用点击类型**:`PICKUP`, `QUICK_MOVE`, `SWAP`, `CLONE`, `THROW`, `QUICK_CRAFT`, `PICKUP_ALL`
- **返回值**:无
- **调用示例**
```Shimmer
self.clickSlot(0, 0, "exampleType")
```
- **示例返回值**
```Shimmer
// 无返回值
```
### `getCarriedItemStack(){:Shimmer}`
- 仅Menu类型包含
- 获取当前鼠标指针上的物品堆
- **参数**:无
- **返回值**:物品堆
- **调用示例**
```Shimmer
self.getCarriedItemStack()
```
- **示例返回值**
```Shimmer
// 会返回一个物品对象,如果为空会返回空物品堆
```
### `delayAction(){:Shimmer}`
- 延迟触发UI的触发器事件
- **参数**:`delay` (延迟时间 毫秒) `actionName` (触发器名称)
- **返回值**:无
- **调用示例**
```Shimmer
self.delayAction(1000, '触发器名称')
```
- **示例返回值**
```Shimmer
// 无返回值
```
### `getHoverScroll(){:Shimmer}`
- 仅Menu类型包含
- 获取当前鼠标悬停的滚动控件列表
- **参数**:无
- **返回值**:无
- **调用示例**
```Shimmer
self.getHoverScroll()
```
- **示例返回值**
```Shimmer
[] // 鼠标悬停的滚动栏控件列表
```
### `create(){:Shimmer}`
- 在当前界面创建一级控件
- **参数**:`tempID` 模板ID、 `newName` 新创建控件的ID
- **返回值**:无
- **调用示例**
```Shimmer
self.create('模板ID', '新控件ID')
```
- **示例返回值**
```Shimmer
// 返回一个控件对象
```
- 好像不是那么好理解,这里放一个带模板的UI配置做例子:比如我们想通过模板在一级创建一个控件,则使用`self.create(‘我是一个模板’, '新控件名称')`
```yaml
ui:
controls:
background:
type: "Texture"
attribute:
width: "1270"
height: "650"
normal: "~inventory/bg.png"
template:
我是一个模板:
type: "Texture"
attribute:
width: "128"
height: "128"
normal: "~inventory/xxx.png"
```
### `slotCount(){:Shimmer}`
- 获取当前 Menu 的容器槽位总数(仅 Menu 类型)
- **参数**:无
- **返回值**:数字类型
- **调用示例**
```Shimmer
self.slotCount()
```
### `get(index){:Shimmer}`
- 通过索引获取顶层控件
- **参数**:`index`(控件索引,数字类型)
- **返回值**:控件对象(找不到时返回 null)
- **调用示例**
```Shimmer
self.get(0)
```
---
## 控件结构
URL: https://wiki.arcartx.com/docs/core/8_ui/6_controls_config
## 控件结构
- 了解完 UI 的基本配置后,接下来介绍控件。单个控件的配置结构如下:
```yaml
background:
type: texture
val: "background" # 可选
attribute:
point: ~middle_center
width: 1000
height: 500
normal: ~AXLoginView/background.png
effect:
stroke:
width: 2
color: ~255,255,255
action:
click: |-
// 点击事件触发器
children:
title:
type: text
attribute:
x: 500
y: 28
center: true
fontSize: 120
texts:
- ~&7&l芜湖
```
- 从配置中不难看出,控件主要是四个部分:类型、属性、子组件、触发器
- 其中:
- `type`是一个非脚本的常量,用来设置组件的类型
- `attribute` 用来设置组件的属性,在此之下的所有值都是脚本语句,而键则是变量名,可通过脚本访问(也就是说你可以自定义属性名,用于实现自定义逻辑)
- `effect` 是纹理控件渲染特效,所有值都是脚本语句,可通过脚本访问修改赋值新建等,具体看控件Shimmer文档。
- `children` 用来设置组件的子组件,是一个嵌套的结构,可以多层嵌套,但不建议层级过深,过深会影响性能。
- `val`是一个非脚本常量,可以不填,用于简化深层结构的访问。例如当结构层级较深时,可能需要编写如下代码:
```Shimmer
val.root['控件A']['控件B']['控件C'].x = 100
```
- 路径过深时代码会变得冗长且不易阅读。此时如果在`控件C`加一个`val: "component"{:yaml}`,即可直接通过`val.component{:Shimmer}`访问该控件。
- `action` 用来创建动作,里面的键是动作名称,值是触发后的脚本内容,当动作的名称和触发器一致时,则在对应事件触发后执行同名动作下的代码。
### 父子组件逻辑
- ArcartX 的 UI 采用相对布局,子组件的位置起点为父组件的左上角(如果设置了锚点则为对应的相对位置,后续章节会详细讲解)。
- 除此之外还有其它的父子级关系,将在控件属性章节的备注中说明。
---
## 控件公共属性
URL: https://wiki.arcartx.com/docs/core/8_ui/7_controls_attribute
## 控件公共属性
以下属性适用于所有类型的控件。
### 基础属性
| 名称 | 说明 | 默认值 | 备注 |
|:-----------:|:------:|:--------:|:------------------------------|
| enable | 是否开启 | true | 关闭后交互性触发器不会触发(影响子组件) |
| visible | 是否可见 | true | 关闭后不可见(影响子组件) |
| width | 宽度 | 0 | |
| height | 高度 | 0 | |
| x | X 坐标 | 0 | 相对于父组件的位置 |
| y | Y 坐标 | 0 | 相对于父组件的位置 |
| scale | 缩放比例 | 1 | 从左上角缩放 |
| middleScale | 中心缩放比例 | 1 | 从正中心缩放 |
| alpha | 透明度 | 1 | 0 为完全透明,1 为完全不透明 |
| rotate | 旋转角度 | 0 | |
| point | 锚点 | TOP_LEFT | 详见下方锚点类型表 |
| through | 穿透 | false | 为 true 时不阻挡下方组件的交互事件,且不接受点击事件 |
### 拖动
| 名称 | 说明 | 默认值 | 备注 |
|:--------:|:------:|:---:|:------------|
| minDragX | 最小拖动 X | 0 | 可拖动的 X 轴最小值 |
| minDragY | 最小拖动 Y | 0 | 可拖动的 Y 轴最小值 |
| maxDragX | 最大拖动 X | 0 | 可拖动的 X 轴最大值 |
| maxDragY | 最大拖动 Y | 0 | 可拖动的 Y 轴最大值 |
### 文本相关
以下属性仅对包含文本显示功能的控件生效:
| 名称 | 说明 | 默认值 | 备注 |
|:---------:|:------:|:------:|:--------------------------|
| texts | 文本内容 | 空 | |
| font | 字体 | 空 | |
| fontSize | 字体大小 | 16 | |
| center | 文字居中 | false | |
| lineSpace | 行间距 | 16 | |
| limit | 字数显示限制 | 999999 | 限制最大显示字数(不含颜色代码),可用于打字机效果 |
### 其它
| 名称 | 说明 | 默认值 | 备注 |
|:------------:|:------:|:---:|:------------------------------|
| limitControl | 限制显示范围 | 空 | 将当前组件的显示范围剪裁为指定组件的范围,传入目标组件对象 |
| tip | 提示信息 | 空 | 仅用于包含 Tip 的组件 |
## 锚点类型
锚点仅在顶层组件(父级是 UI 本身)或父级为 Canvas、Adaptive 时生效。
| 锚点类型 | 说明 |
|:--------------------------|:---------------------|
| horizontal_stretch_top | 宽度跟随父级,置于顶部 |
| horizontal_stretch_middle | 宽度跟随父级,置于中间 |
| horizontal_stretch_bottom | 宽度跟随父级,置于底部 |
| vertical_stretch_left | 高度跟随父级,置于左侧 |
| vertical_stretch_center | 高度跟随父级,置于正中 |
| vertical_stretch_right | 高度跟随父级,置于右侧 |
| stretch_all | 完全跟随父级宽高,x 和 y 锁定为 0 |
| top_left | 左上角 |
| top_center | 顶部中间 |
| top_right | 右上角 |
| middle_left | 左中间 |
| middle_center | 正中间 |
| middle_right | 右中间 |
| bottom_left | 左下角 |
| bottom_center | 底部中间 |
| bottom_right | 右下角 |
## 图形效果
- 以下内容适用于任何带有渲染纹理(贴图、色块)的控件,它会对纹理的渲染表现进行附加处理,实现更精美的UI
### 形状与圆角
| 名称 | 说明 | 默认值 | 备注 |
|:------:|:----:|:----:|:----------------------------------------------------|
| shape | 形状类型 | RECT | 可选值:`RECT`(矩形)、`ROUNDED_RECT`(圆角矩形)、`CIRCLE`(圆形/椭圆) |
| radius | 圆角半径 | 5 | 当 shape 为 `ROUNDED_RECT` 时生效 |
### 纹理表达方式说明
- 对于纹理渲染,后续我将在控件属性说明中 以 `纹理表达式` 指代
| 类型 | 说明 | 语法 |
|:------:|:------------------------------:|:----------------------------------------------:|
| 图像 | 直接填写资源路径进行对应图片的渲染,支持PNG GIF 网链 | xxx.png / xxx.gif / https://xxx.com/xxx.png |
| 玩家头像 | 取指定UUID玩家的正版皮肤头像 | PlayerSkin:xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
| RGBA色块 | 根据RGBA表达式渲染颜色 | 255,255,255,255 |
| 毛玻璃 | 高斯模糊的块,后面这个语法示例的30是模糊度 | Frosted:30;255,255,255,80 |
- 请注意,虽然我这里语法写的都不带`~`这是为了举例更清晰,但是如果你属性值是纯文本,一定记得标记纯文本 比如 `normal: ~xxx.png`
### 纹理特效
- 纹理特效位于控件的 `effect` 块中,每种特效作为一个子节点配置。以下是 ArcartX 支持的所有特效类型。
```yaml
attribute:
x: 0
y: 0
# 下文略
effect:
stroke:
width: 2
color: ~255,255,255
shadow:
xOffset: 3
yOffset: 3
blur: 6
color: ~0,0,0,100
neon:
color: ~0,0,100
size: 8
intensity: 1
animated: true
ripple:
duration: 1200
color: ~255,255,255,100
width: 0.1
gradient:
color1: ~255,0,0,100
color2: ~0,0,255,50
type: 1
angleDeg: 90
flow:
color: ~255,255,255
speed: 1
width: 0.1
angleDeg: 60
mode: 0
energy:
color: ~0,0,255
intensity: 1
frequency: 1
speed: 1
pattern: 2
```
#### 描边 (stroke)
为控件添加边框描边效果。
| 参数 | 类型 | 说明 |
|:------|:-----:|:-----|
| width | float | 描边宽度 |
| color | RGBA | 描边颜色 |
#### 阴影 (shadow)
为控件添加投影效果。
| 参数 | 类型 | 说明 |
|:--------|:-----:|:------|
| xOffset | float | X 轴偏移 |
| yOffset | float | Y 轴偏移 |
| blur | float | 模糊程度 |
| color | RGBA | 阴影颜色 |
#### 霓虹 (neon)
为控件添加发光霓虹效果。
| 参数 | 类型 | 说明 |
|:----------|:-------:|:---------|
| color | RGBA | 霓虹颜色 |
| size | float | 发光范围 |
| intensity | float | 发光强度 |
| animated | boolean | 是否启用呼吸动画 |
#### 波纹 (ripple)
点击时产生水波纹扩散效果。
| 参数 | 类型 | 说明 |
|:---------|:-----:|:---------|
| duration | int | 持续时间(毫秒) |
| color | RGBA | 波纹颜色 |
| width | float | 波纹宽度 |
#### 渐变 (gradient)
为控件添加颜色渐变效果。
| 参数 | 类型 | 说明 |
|:---------|:-----:|:---------------------------------|
| color1 | RGBA | 起始颜色 |
| color2 | RGBA | 结束颜色 |
| type | int | 渐变类型:`0` 线性、`1` 径向、`2` 角度、`3` 菱形 |
| angleDeg | float | 渐变角度(度) |
#### 流光 (flow)
为控件添加流动光效。
| 参数 | 类型 | 说明 |
|:---------|:-----:|:---------------------------|
| color | RGBA | 流光颜色 |
| speed | float | 流动速度 |
| width | float | 光带宽度 |
| angleDeg | float | 流动角度(度) |
| mode | int | 流光模式:`0` 线性、`1` 环形、`2` 对角线 |
#### 能量 (energy)
为控件添加能量场效果。
| 参数 | 类型 | 说明 |
|:----------|:-----:|:----------------------------------|
| color | RGBA | 能量颜色 |
| intensity | float | 强度 |
| frequency | float | 频率 |
| speed | float | 速度 |
| pattern | int | 图案类型:`0` 脉冲、`1` 波浪、`2` 电弧、`3` 等离子 |
#### 饼图剪裁 (pie)
| 参数 | 类型 | 说明 |
|:-----------|:-----:|:------------------------------------------|
| startAngle | float | 起始角度(注意,0度的位置是真的0度而不是图形顶部中间的位置,而是右侧中间的位置) |
| endAngle | float | 结束角度 |
| centerX | float | 中心 X 比例 (正中间就写0.5) |
| centerY | float | 中心 Y 比例 (正中间就写0.5) |
| feather | float | 边缘羽化 |
---
## 控件类型
URL: https://wiki.arcartx.com/docs/core/8_ui/8_controls_type
## 控件类型
ArcartX 提供了多种类型的控件,根据需要选择合适的控件类型。
## 基础显示
### 纹理 `Texture`
- 用于显示色块或图像,支持 png、jpg、gif 格式
- 支持文本显示
- 渲染玩家头像:在 normal 属性填写 `PlayerSkin:UUID`(UUID 为目标玩家的 UUID)
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:------:|:--------:|:-----:|:--------------------------------------------------------------------:|
| normal | 常态显示内容 | 无 | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明) |
| hover | 鼠标悬停显示内容 | 无 | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明),不设置则悬停时也渲染常态图 |
| loop | GIF 是否循环 | false | 为 false 时 GIF 停止于最后一帧 |
Texture 控件的 GIF 动画可通过 Shimmer 脚本调用 `self.replay()` 重置到第一帧重新播放。
### 文字 `Text`
- 用于显示纯文字内容,支持 ArcartX 的特殊格式码(描边、渐变、流光等)。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:---------:|:------:|:-----:|:------------------------------------------|
| shadow | 渲染阴影 | false | |
| alignment | 文字对齐方式 | left | 可选值:`left`(左对齐)、`center`(居中)、`right`(右对齐) |
### 九宫格纹理 `9SliceTexture`
- 九宫格纹理用于显示色块或者图像,图像读取支持png、jpg、gif
- 九宫格纹理组件支持文本显示
- 九宫格纹理和纹理组件的机制相同,但是会将被渲染的贴图剪裁成9个块:
- 如图所示,九宫格纹理会根据 `left``right``top``bottom``textureWidth``textureHeight`将贴图分为9个部分
- 其中,四角不会被拉伸(例图淡紫色充填部分),其余根据`width`以及`height`进行拉伸。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:-------------:|:-----------:|:---:|:----------------------------------------------------------------------------:|
| normal | 常态显示内容 | 无 | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明) |
| hover | 鼠标悬停上方显示的内容 | 无 | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明) ,如果不设置该值则就算悬停了也是渲染常态图 |
| left | 左侧分割线 | 0 | 左侧分割线宽度 |
| right | 右侧分割线 | 0 | 右侧分割线宽度 |
| top | 上侧分割线 | 0 | 上分割线高度 |
| bottom | 下侧分割线 | 0 | 下分割线高度 |
| textureWidth | 贴图宽度 | 0 | 贴图宽度(可以和贴图实际宽度不一样,分割以该数据为准) |
| textureHeight | 贴图高度 | 0 | 贴图高度(可以和贴图实际高度不一样,分割以该数据为准) |
## 游戏内容显示
### 实体 `Entity`
- 实体组件用于显示游戏内实体,比如背包UI的玩家。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:-----------:|:--------:|:-------------:|:--:|
| uuid | 渲染实体uuid | 当前客户端玩家自身uuid | |
| hideTag | 是否渲染名称标签 | false | |
| followMouse | 视线是否跟随鼠标 | false | |
### 模型 `Model`
- 用于在 UI 中渲染一个模型。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:-----------:|:--------:|:-----:|:---------------------------------------------------------------------------|
| model | 模型 ID | 无 | |
| animation | 播放动作 | idle | |
| followMouse | 视线是否跟随鼠标 | false | |
| showType | 显示部位类型 | none | 可选值:`none`(完整模型)、`HEAD`(头部)、`UPPER_BODY`(上半身)、`LOWER_BODY`(下半身)、`FOOT`(脚部) |
### 槽位 `Slot`
- 物品格子控件,用于显示和交互物品。
- itemEffect 填写 ItemEffect 配置文件名:配置位于 `ArcartX/item_effect/xxx.yml` 则填写 `xxx`,带子目录如 `ArcartX/item_effect/abc/xxx.yml` 则填写 `abc/xxx`。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:-------------:|:--------:|:--------:|:-----------------------------------------------------------------------------------------------:|
| normal | 常态显示内容 | 无 | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明) |
| hover | 鼠标悬停显示内容 | 无 | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明) ,不设置则悬停时也渲染常态图。HUD 类型中,手持槽位对应该槽位时也会渲染此纹理 |
| slotType | 槽位类型 | Backpack | `Container` 容器槽位 `Extra`自定义拓展槽位 |
| id | 槽位ID | 0 | 除了拓展槽位是字符串,其余两种都是数字ID |
| itemScale | 物品缩放比例 | 1.0 | 物品缩放比例 |
| lock | 锁定点击 | false | 是否锁定点击事件,锁定后无法点击槽位物品(仅客户端) |
| cooldown | 物品冷却状态贴图 | | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明) ,物品在渲染冷却进度时候的贴图 |
| overwriteText | 覆盖显示 | 无 | 当不为空时,会替换物品右下角的文字显示 |
在 HUD 类型的 UI 中,Slot 控件支持 hovered 检测:当玩家手持的物品对应该槽位时,会渲染 `hover` 纹理。
### 多层血条 `BossBar`
- 多层血条组件用于显示UI血条,该控件不应该直接放入UI而是在插件的boss_bar模块进行配置。
- 具体请查看BossBar相关说明
- 可用变量:health、maxHealth、layer(剩余层数)
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:--------------:|:--------:|:---:|:-----------------------------:|
| textures | 纹理列表 | 无 | 填写纹理路径列表,支持网络资源直连链接【注意这个是个列表】 |
| transitionTime | 过渡时间(毫秒) | 500 | 血条宽度过渡时长 |
## 特殊控件
### 罗盘 `Compass`
- 一个长得很像游标卡尺的指南针,联动WayPoint进行更精确的位置指引
| 名称 | 说明 | 默认值 | 备注 |
|:------------------:|:-------:|:-----------:|:------------------------------------------------------:|
| background | 背景纹理 | 0,0,0,180 | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明) |
| textColor | 文字颜色 | 255,255,255 | |
| tickColor | 刻度颜色 | 255,255,255 | |
| directionColor | 方位颜色 | 255,255,255 | |
| tickInterval | 刻度间隔 | 5 | |
| majorTickInterval | 主要刻度间隔 | 15 | |
| showWaypoints | 显示路标图标 | true | |
| waypointFontSize | 路标文字尺寸 | 32 | |
| waypointIconWidth | 路标图标宽度 | 16 | |
| waypointIconHeight | 路标图标高度 | 16 | |
| wayOffsetY | 路标起始Y偏移 | 0 | |
### 输入框 `TextBox`
- 输入框组件用于接收用户输入的文本内容。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:------------:|:-----------:|:------------:|:---------------------------------------------------------------:|
| length | 最大输入长度 | 99999 | |
| allowNewLine | 是否允许换行 | false | |
| editable | 是否可编辑 | true | |
| cursorColor | 光标颜色 | ~151,255,255 | |
| emptyText | 输入框为空时的提示文本 | 无 | |
| canLoseFocus | 是否可以失去焦点 | true | |
| background | 输入框背景颜色 | 无 | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明) 如果为空则不渲染 |
| passwordChar | 密码字符 | 无 | 为空则正常渲染文字 |
| inputPattern | 输入限制 | 无 | 这里输入的是正则表达式,比如限制仅限数字输入则是 `[0-9]+{:yaml}` |
### 进度条 `Progress`
- 该控件自带缓动过度动画,通过一个比值进行自动伸缩,可设置从左到右、右到左、上到下、下到上几种模式。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:--------:|:----:|:---:|:------------------------------------------------------:|
| texture | 纹理 | 无 | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明) |
| progress | 进度比值 | 0 | 取值范围0~1,0表示无进度,1表示满进度 |
| time | 缓动时间 | 100 | 进度变化到目标值所需时间,单位毫秒 |
| mode | 进度模式 | 0 | 0 从左到右 1 从右到左 2 从上到下 3 从下到上 |
### 导入器 `Import`
- 导入器用于将其它UI中的控件导入到当前UI中
- 注:该控件无子控件
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:----:|:----:|:---:|:------:|
| node | 节点路径 | | 填写节点路径 |
- 详细说明
```yaml
import:
type: import
attribute:
node: ~menu.test.adaptive.chat
# 这里注意,如果目标ui是hud,第一个节点填hud,反之填menu
# 第二个节点是目标ui的id
# 其余节点填目标ui的控件路径,需要从顶层控件开始,用点号分隔
# 比如我要导入目标ui的abc中的子控件bcd,则路径为abc.bcd
```
### 观察者 `Observer`
- 观察者用于订阅一个 *字典类型* 的变量,当变量键数量发生变化时,创建/删除控件
- 注:该控件无子控件
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:---------:|:----:|:---:|:------------------------------------------:|
| maxSize | 最大数量 | 32 | |
| subscribe | 订阅变量 | | 必须是字典类型,一般情况下填写变量 |
| target | 目标控件 | | 填写控件变量,当订阅目标增加键时,复制该控件,减少键时,删除该键对应的复制出来的控件 |
- 详细说明
```yaml
obs:
type: observer
attribute:
target: val.vStack['test'] # 不要给被复制控件加val,而是给父级设置val值
subscribe: global.testMap # 订阅目标值
adaptive:
type: adaptive
attribute:
point: ~bottom_left
width: 1920
height: 1080
children:
vStack:
val: "vStack"
type: vStack
children:
test:
type: texture
attribute:
width: 200
height: 100
texts: "'键:' + self.key" # 复制出来的控件会有一个key变量,对应订阅变量的键
normal: ~0,0,0
fontSize: 32
```
## 聊天相关
### 聊天栏输入框 `ChatTextBox`
- 和TextBox类似,但聊天栏输入框包含专用于聊天栏输入框的特性,该控件下可创建补全器子控件用于命令补全。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:------------:|:-----------:|:------------:|:------------------------------------------------------:|
| length | 最大输入长度 | 99999 | |
| editable | 是否可编辑 | true | |
| cursorColor | 光标颜色 | ~151,255,255 | |
| emptyText | 输入框为空时的提示文本 | 无 | |
| canLoseFocus | 是否可以失去焦点 | true | |
| background | 输入框背景颜色 | 无 | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明) |
| sendClose | 发送后关闭UI | TRUE | |
### 命令补全器 `Suggestion`
- 命令补全器用于聊天栏的命令补全,注意这个控件只能作为聊天栏输入框控件的子控件
- 注:该控件无子控件
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:----------------:|:----------:|:---------:|:------------------------------------------------------:|
| background | 背景色 | 0,0,0,175 | [纹理表达式](/docs/core/8_ui/7_controls_attribute#纹理表达方式说明) |
| radius | 圆角半径 | 3 | |
| spaceBetween | 每个提示文字的间距 | 5 | |
| backgroundBorder | 提示文字和背景的间距 | 5 | |
| up | 位置置于聊天栏上方 | false | 反之至于下方 |
| maxShow | 最多显示的提示数量 | 5 | |
| textColor | 提示文字颜色 | #FFFFFF | 注意这里填的是HEX16颜色 |
| hoverTextColor | 悬停提示文字颜色 | #87CEEB | 注意这里填的是HEX16颜色 |
- 详细说明
```yaml
input:
type: ChatTextBox
attribute:
length: 64
background: ~0,0,0
x: 10
y: 700
fontSize: 32
width: 1000
height: 20
children:
# 注意看这里,Suggestion只能置于聊天栏输入框的子控件
suggestion:
type: Suggestion
attribute:
fontSize: 32
```
### 聊天栏 `Chat`
- 聊天栏用于显示聊天消息。该聊天栏支持ArcartX的特殊颜色格式和文字图标以及卡片消息
- 注:该控件无子控件
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:------------:|:-----:|:-----:|:---------------------------------:|
| border | 边框宽度 | 5 | |
| spaceBetween | 每行的间距 | 5 | |
| background | 背景颜色 | 0,0,0 | 填写rgba颜色字符串,比如~0,0,0,175 |
| filter | 过滤 | | 默认为空,当存在值时,如果消息开头和这个设定的值匹配才会显示 |
| showCard | 显示卡片 | true | 关闭后该聊天栏不显示卡片消息 |
| exclude | 排除 | | 默认为空,当存在值时,如果消息开头为设置的值则排除对应消息 |
| keep | 持续渲染 | false | 为 true 时,即使不在聊天屏幕中也持续显示所有消息(不会淡出) |
## 布局型
### 画布 `Canvas`
- 画布组件用于布局,你可以将其它组件放置在画布中进行相对布局。画布类型无独有属性。
### 自适配布局 `Adaptive`
- 自适配布局用于根据窗口大小调整其子组件的缩放值。
- 自适配布局同样没有独有属性,但是有必要详细说明一下。
- 该组件的宽高属性应该设置为你编辑这个UI的时候的屏幕分辨率宽高。这样就会在不同分辨率中运算缩放并应用到子组件中。
- 比如你的屏幕分辨率是1920 * 1080 那么将该组件的宽高设置为同样的值即可。
- 此外,还需要说明一点,自适配布局组件本身的位置是不会变的,也就是比如你窗口本身是居中的,那么自适配布局应该设置为居中锚点,如果需要其它位置以此类推。
### 横向网格布局 `HGrid` (别名`Grid`)
- 网格布局用于将子组件根据设定的间距和列数有序排列(比如背包的槽位)
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:-------------:|:----:|:---:|:----------:|
| spaceBetweenX | X轴间距 | 0 | 子组件之间的水平间距 |
| spaceBetweenY | Y轴间距 | 0 | 子组件之间的垂直间距 |
| column | 列数 | 1 | 子组件的列数 |
### 纵向网格布局 `VGrid`
- 网格布局用于将子组件根据设定的间距和列数有序排列(比如背包的槽位)
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:-------------:|:----:|:---:|:----------:|
| spaceBetweenX | X轴间距 | 0 | 子组件之间的水平间距 |
| spaceBetweenY | Y轴间距 | 0 | 子组件之间的垂直间距 |
| row | 行数 | 1 | 子组件的行数 |
### 横向布局 `HStack` (别名`Stack`)
- 横向布局用于将子组件横向排列
- 该类型控件允许子控件增加一条新属性: level, 子控件 level越高,越靠前,其余顺序逻辑不变。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:------------:|:----:|:---:|:---------------------------:|
| spaceBetween | 间距 | 0 | 子组件之间的间距 |
| maxSize | 最大数量 | 64 | 一级子控件最大数量,如果超过该值,将移除最先加入的控件 |
### 竖向布局 `VStack`
- 竖向布局用于将子组件竖向排列
- 该类型控件允许子控件增加一条新属性: level, 子控件 level越高,越靠前,其余顺序逻辑不变。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:------------:|:----:|:---:|:---------------------------:|
| spaceBetween | 间距 | 0 | 子组件之间的间距 |
| maxSize | 最大数量 | 64 | 一级子控件最大数量,如果超过该值,将移除最先加入的控件 |
### 滚动栏 `Scroll`
- 滚动栏用于实现可滚动的内容区域。
- 滚动栏中只允许有一个子控件,且只能是布局控件(不能为 `Tip` 或 `Scroll`)。
- 滚动栏本身不带滚动交互,需要配合滑块控件通过比例值控制滚动位置。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:-----:|:-------:|:---:|:--:|
| moveX | 横向移动百分比 | 0 | |
| moveY | 纵向移动百分比 | 0 | |
- 这个滚动栏控件解释起来有点困难,直接上一个示例。
```yaml
controls:
adaptive:
type: adaptive
attribute:
point: ~middle_center
width: 1920
height: 1080
children:
背景:
type: Texture
attribute:
point: ~middle_center
width: 1270
height: 650
normal: ~0,0,0
滚动栏区域:
type: Canvas
attribute:
point: ~middle_center
width: 1270
height: 650
children:
纵向滑块:
type: Texture
attribute:
point: ~top_right
width: 25
height: 80
normal: ~255,255,255
maxDragY: 650 - 80
横向滑块:
type: Texture
attribute:
point: ~bottom_left
width: 80
height: 25
normal: ~255,255,255
maxDragX: 1270 - 80
滚动栏:
type: Scroll
attribute:
width: 1245
height: 625
moveY: self.parent['纵向滑块'].getDragYRatio()
moveX: self.parent['横向滑块'].getDragXRatio()
normal: ~255,255,255
children:
滚动栏区域:
type: Canvas
attribute:
width: 1270
height: 1000
children:
示例控件:
type: Texture
attribute:
width: 1270
height: 1000
normal: ~inventory/item.png
```
### 血条排列器 `BossBars`
- 血条排列器用于自动创建、移除、布局血条控件,创建好了不需要做任何事情,该控件会根据服务端配置的BossBar自动处理
- 如何创建血条配置请看BossBar使用说明。
- 注:该控件无子控件
- 每次创建血条,会根据配置,在顶层控件加入一个entityName变量,表示当前血条所绑定的实体名称。
- 独有属性:
| 名称 | 说明 | 默认值 | 备注 |
|:------------:|:----:|:---:|:---------------------------:|
| spaceBetween | 间距 | 0 | 子组件之间的间距 |
| maxSize | 最大数量 | 3 | 一级子控件最大数量,如果超过该值,将移除最先加入的控件 |
---
## 控件触发器
URL: https://wiki.arcartx.com/docs/core/8_ui/9_controls_action
## 控件触发器
控件触发器用于响应用户的交互操作。在控件的 `action` 中配置触发器名称和对应的 Shimmer 脚本即可。
### 鼠标交互
| 名称 | 说明 | 备注 |
|:-------------:|:--------:|:--------------------------------------------|
| click | 鼠标点击 | 任意按键点击 |
| clickLeft | 左键点击 | |
| clickRight | 右键点击 | |
| clickMiddle | 中键点击 | |
| release | 鼠标释放 | 任意按键释放 |
| releaseLeft | 左键释放 | |
| releaseRight | 右键释放 | |
| releaseMiddle | 中键释放 | |
| enter | 鼠标进入控件范围 | |
| leave | 鼠标离开控件范围 | |
| wheel | 鼠标滚轮 | 通过 `self.wheelValue{:Shimmer}` 获取滚动值,正负代表方向 |
### 键盘交互
| 名称 | 说明 | 备注 |
|:----------:|:----:|:---------------------------------|
| keyPress | 按键按下 | 通过 `self.keyCode{:Shimmer}` 获取按键 |
| keyRelease | 按键释放 | 通过 `self.keyCode{:Shimmer}` 获取按键 |
### 生命周期
| 名称 | 说明 | 备注 |
|:----------:|:-------:|:---------------------------|
| create | 控件被创建时 | |
| remove | 控件被删除时 | 关闭 UI 不会触发此事件 |
| textChange | 输入框内容变化 | 仅 TextBox / ChatTextBox 控件 |
触发器中的脚本通过 `self` 访问当前控件对象,可以读取控件属性、调用控件函数。
---
## Tooltips 说明
URL: https://wiki.arcartx.com/docs/core/9_tip/1_info
## Tooltips 使用说明
Tooltips 的配置格式与 UI 类似,但存在一些限制。如果你还没有阅读 UI 篇,建议先了解 UI 系统后再来看这部分。
## Tooltips 和 UI 的差异
- Tooltips 本体不支持触发器
- Tooltips 中无法创建实体模型控件和输入框控件
- Tooltips 的控件触发器不支持交互性(鼠标、键盘)事件
- Tooltips 没有 `controls` 块,而是使用 `root_control`
## 基本配置结构
Tooltips 配置位于 ArcartX 配置目录下的 `tooltip` 文件夹,支持创建多个配置文件。
```yaml
tip:
match: "default"
root_control:
type: "Tip"
attribute:
width: 1920
height: 1080
autoScale: true
follow: false
```
### 配置项说明
| 配置项 | 说明 |
|:-------------------------|:------------------------------------------------------|
| tip.match | 匹配规则。当 Tooltips 的第一行或第二行(名称和第一行 lore)包含此文字时,替换为该配置的内容 |
| root_control.type | 控件类型,必须为 `Tip` |
| attribute.width / height | 配置所使用的分辨率,用于自动缩放计算 |
| attribute.autoScale | 是否按照设定的宽高进行自动缩放。不需要自动缩放时可省略 |
| attribute.follow | 是否跟随鼠标移动(默认 true) |
### 匹配规则
- `match` 填写 `default` 时,匹配所有未被其它配置匹配到的 Tooltips
- `match` 也会匹配物品 NBT 中 `type` 字段的值
- `match` 支持列表格式,可以配置多个匹配规则
## 注意事项
1. Tips 的文字获取和当前渲染物品的获取,请参考 Shimmer 工具集文档中的 Tip 函数
2. Tips 中可以使用 Slot 控件来渲染对应物品,只需将槽位类型设置为 `Hover`,不需要填写 ID
---
## 尝试编写一个Tooltips
URL: https://wiki.arcartx.com/docs/core/9_tip/2_try
## 尝试编写一个Tooltips
- 下面我们尝试编写一个Tooltips
### 准备工作
- 新建文件 `ArcartX/tooltip/默认.yml`
### 准备资源文件
### 书写一个简单的Tooltip
- 这里注意:Tip下的控件总宽高是根据顶层控件总宽高自动运算的
```yaml
tip:
match: "default"
# 这里填写default则是默认匹配
root_control:
type: "Tip"
attribute:
width: 1920
height: 1080
autoScale: true
children:
panel:
# 以一个画布控件作为基础,方便我们下面的控件使用锚点对齐
type: Canvas
attribute:
# 这里这个100是左右两边的边缘宽度 + 显示文字的宽度(根据名称或者lore控件的渲染宽度最大值)
width: 100 + Math.max(val.display.width, val.lore.width)
# 这里这个156是上下两边的边缘高度 + 槽位高度 + 名称文字高度 + 显示文字的高度(lore控件的渲染高度)
height: 156 + val.lore.height
children:
background:
# 背景控件使用9SliceTexture,自动根据大小切分九宫格处理拉伸,如果根组件开启自动缩放,四角也会跟随缩放
type: 9SliceTexture
attribute:
textureWidth: 256
textureHeight: 256
normal: ~tips/background.png
left: 16
right: 16
top: 16
bottom: 16
# 使用stretch_all使该控件宽高完全跟随父级宽高
point: ~stretch_all
# 下面这几个控件您只要看过UI的教学都应该会用了,不做过多赘述。
slot:
type: Slot
attribute:
width: 80
height: 80
normal: ~tips/slot.png
slotType: ~Hover
itemScale: "0.5"
point: ~top_center
y: 15
display:
type: Text
val: display
attribute:
texts: Tip.getDisplay()
fontSize: 40
point: ~top_center
y: 105
text:
type: Text
val: lore
attribute:
texts: Tip.getLore()
fontSize: 38
x: 16
y: 140
```
### 效果
---
## 客户端初始化事件
URL: https://wiki.arcartx.com/docs/server_api/15_events/1_initialized
## 客户端初始化事件
- `ClientInitializedEvent` 是一个抽象类,包含四个子事件,对应客户端初始化的不同阶段。
- 这些事件在玩家安装了ArcartX客户端模组并连接服务器时按顺序触发。
## `ClientInitializedEvent.Start`
- 客户端开始初始化时触发,此时客户端刚与服务端建立ArcartX通道
- **属性**:`player`: Player — 玩家
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onStart(ClientInitializedEvent.Start event) {
Player player = event.getPlayer();
// 客户端开始初始化
}
```
## `ClientInitializedEvent.End`
- 客户端初始化完成时触发,此时客户端已准备就绪
- **属性**:`player`: Player — 玩家
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onEnd(ClientInitializedEvent.End event) {
Player player = event.getPlayer();
// 可以开始向客户端发送数据了
}
```
## `ClientInitializedEvent.Reload`
- 客户端重载时触发,通常由玩家在客户端手动触发重载
- **属性**:`player`: Player — 玩家
- **可取消**:否
## `ClientInitializedEvent.ResourceLoaded`
- 客户端资源加载完成时触发,此时客户端已完成所有资源文件的加载
- **属性**:`player`: Player — 玩家
- **可取消**:否
- 适合在此事件中发送需要资源就绪后才能显示的内容(如UI、模型等)
---
## 客户端通信事件
URL: https://wiki.arcartx.com/docs/server_api/15_events/2_communication
## 客户端通信事件
- 与客户端网络通信相关的事件。
## `ClientChannelEvent`
- 客户端ArcartX通道建立时触发
- **属性**:`player`: Player — 玩家
- **可取消**:否
## `ClientCustomPacketEvent`
- 收到客户端发来的自定义数据包时触发
- 这是实现客户端与服务端自定义通信的核心事件
- **属性**:
- `player`: Player — 发送数据的玩家
- `id`: String — 数据包ID
- `data`: List<String> — 数据内容列表
- `argSize`: int — 参数数量
- **可取消**:否
**内置参数解析方法**:
`ClientCustomPacketEvent` 提供了一系列便捷方法来解析参数,解析失败时会返回默认值而不是抛出异常:
| 方法 | 返回类型 | 失败默认值 |
|------|----------|------------|
| `getArg(index)` | String | `""` |
| `getArgAsInt(index)` | int | `0` |
| `getArgAsDouble(index)` | double | `0.0` |
| `getArgAsBoolean(index)` | boolean | `false` |
| `getArgAsLong(index)` | long | `0` |
| `getArgAsFloat(index)` | float | `0` |
| `getArgAsUUID(index)` | UUID? | `null` |
- **调用示例**
```java
@EventHandler
public void onCustomPacket(ClientCustomPacketEvent event) {
if (event.getId().equals("my_plugin:action")) {
String action = event.getArg(0);
int value = event.getArgAsInt(1);
// 处理自定义数据包
}
}
```
---
## 客户端按键事件
URL: https://wiki.arcartx.com/docs/server_api/15_events/3_key
## 客户端按键事件
- 与客户端按键操作相关的事件,分为客户端按键和简单按键两类。
## `ClientKeyPressEvent`
- 客户端按键按下时触发(对应通过 `registerClientKeyBind` 注册的按键)
- **属性**:
- `player`: Player — 玩家
- `keyName`: String — 按键名称
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onKeyPress(ClientKeyPressEvent event) {
if (event.getKeyName().equals("open_menu")) {
// 玩家按下了自定义按键
}
}
```
## `ClientKeyReleaseEvent`
- 客户端按键释放时触发
- **属性**:
- `player`: Player — 玩家
- `keyName`: String — 按键名称
- **可取消**:否
## `ClientKeyGroupPressEvent`
- 按键组触发时触发,当一组按键同时按下时产生
- **属性**:
- `player`: Player — 玩家
- `groupID`: String — 按键组ID
- **可取消**:否
## `ClientSimpleKeyPressEvent`
- 简单按键按下时触发(对应通过 `registerSimpleKeyBind` 注册的按键)
- **属性**:
- `player`: Player — 玩家
- `keyName`: String — 按键名称
- **可取消**:否
## `ClientSimpleKeyReleaseEvent`
- 简单按键释放时触发
- **属性**:
- `player`: Player — 玩家
- `keyName`: String — 按键名称
- **可取消**:否
---
## 客户端实体视野事件
URL: https://wiki.arcartx.com/docs/server_api/15_events/4_entity
## 客户端实体视野事件
- 当实体进入或离开玩家客户端的渲染视野时触发。
## `ClientEntityJoinEvent`
- 实体进入玩家客户端视野时触发
- **属性**:
- `player`: Player — 玩家
- `entityUUID`: UUID — 进入视野的实体UUID
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onEntityJoin(ClientEntityJoinEvent event) {
UUID entityUUID = event.getEntityUUID();
// 实体进入了玩家的视野
}
```
## `ClientEntityLeaveEvent`
- 实体离开玩家客户端视野时触发
- **属性**:
- `player`: Player — 玩家
- `entityUUID`: UUID — 离开视野的实体UUID
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onEntityLeave(ClientEntityLeaveEvent event) {
UUID entityUUID = event.getEntityUUID();
// 实体离开了玩家的视野
}
```
---
## 客户端UI事件
URL: https://wiki.arcartx.com/docs/server_api/15_events/5_ui
## 客户端UI事件
- 与ArcartX自定义UI界面相关的事件,分为HUD和菜单两类。
## `ClientHudOpenEvent`
- HUD界面打开时触发
- **属性**:
- `player`: Player — 玩家
- `hud`: ArcartXUI — HUD对象
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onHudOpen(ClientHudOpenEvent event) {
String hudId = event.getHud().getId();
// HUD已打开
}
```
## `ClientHudCloseEvent`
- HUD界面关闭时触发
- **属性**:
- `player`: Player — 玩家
- `hud`: ArcartXUI — HUD对象
- **可取消**:否
## `ClientMenuOpenEvent`
- 菜单界面打开时触发
- **属性**:
- `player`: Player — 玩家
- `menu`: ArcartXUI — 菜单对象
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onMenuOpen(ClientMenuOpenEvent event) {
String menuId = event.getMenu().getId();
// 菜单已打开
}
```
## `ClientMenuCloseEvent`
- 菜单界面关闭时触发
- **属性**:
- `player`: Player — 玩家
- `menu`: ArcartXUI — 菜单对象
- **可取消**:否
---
## 客户端槽位事件
URL: https://wiki.arcartx.com/docs/server_api/15_events/6_slot
## 客户端槽位事件
- 与ArcartX额外槽位系统相关的事件。
## `ClientExtraSlotClickEvent`
- 玩家点击额外槽位时触发
- **属性**:
- `player`: Player — 玩家
- `slotID`: String — 槽位ID
- `buttonID`: int — 鼠标按键ID
- **可取消**:是
- **调用示例**
```java
@EventHandler
public void onSlotClick(ClientExtraSlotClickEvent event) {
if (event.getSlotID().equals("ring_1")) {
// 玩家点击了戒指槽位
}
}
```
这是少数可取消的事件之一。取消后客户端不会执行默认的槽位交互行为。
## `ClientExtraSlotRequestEvent`
- 客户端请求额外槽位数据时触发,通常在客户端初始化或UI打开时自动发送
- **属性**:
- `player`: Player — 玩家
- `slotID`: String — 槽位ID
- **可取消**:否
---
## 客户端输入事件
URL: https://wiki.arcartx.com/docs/server_api/15_events/7_input
## 客户端输入事件
- 与玩家鼠标操作和移动状态相关的事件。
## `ClientMouseClickEvent`
- 玩家鼠标点击时触发
- **属性**:
- `player`: Player — 玩家
- `button`: int — 鼠标按键(0=左键,1=右键,2=中键)
- `action`: int — 动作类型
- **可取消**:是
- **调用示例**
```java
@EventHandler
public void onMouseClick(ClientMouseClickEvent event) {
if (event.getButton() == 0) {
// 左键点击
}
}
```
## `ClientMoveBreakEvent`
- 玩家移动打断时触发,通常在播放动画或执行动作时玩家移动会触发此事件
- **属性**:`player`: Player — 玩家
- **可取消**:是
- **调用示例**
```java
@EventHandler
public void onMoveBreak(ClientMoveBreakEvent event) {
// 玩家移动打断了当前动作
}
```
---
## 玩家事件
URL: https://wiki.arcartx.com/docs/server_api/15_events/8_player
## 玩家事件
- 由服务端玩家状态变化触发的事件,与客户端事件不同,这些事件在服务端逻辑中产生。
## `PlayerAreaEnterEvent`
- 玩家进入ArcartX区域时触发
- **属性**:
- `player`: Player — 玩家
- `area`: Area — 进入的区域对象
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onAreaEnter(PlayerAreaEnterEvent event) {
String areaName = event.getArea().getName();
// 玩家进入了区域
}
```
## `PlayerAreaLeaveEvent`
- 玩家离开ArcartX区域时触发
- **属性**:
- `player`: Player — 玩家
- `area`: Area — 离开的区域对象
- `newArea`: Area? — 新进入的区域(如果直接从一个区域进入另一个区域),可能为null
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onAreaLeave(PlayerAreaLeaveEvent event) {
Area newArea = event.getNewArea();
if (newArea != null) {
// 玩家从一个区域直接进入了另一个区域
} else {
// 玩家离开区域进入了无区域地带
}
}
```
## `PlayerExtraSlotUpdateEvent`
- 玩家额外槽位物品更新时触发(通过 `ArcartXPlayer.setSlotItemStack` 设置时)
- **属性**:
- `player`: Player — 玩家
- `slotID`: String — 槽位ID
- `itemStack`: ItemStack — 更新后的物品
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onSlotUpdate(PlayerExtraSlotUpdateEvent event) {
String slotID = event.getSlotID();
ItemStack item = event.getItemStack();
// 槽位物品已更新
}
```
## `PlayerModelUpdateEvent`
- 玩家模型更新时触发(通过 `ArcartXPlayer.setModel` 设置时)
- **属性**:
- `player`: Player — 玩家
- `modelID`: String — 新模型ID
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onModelUpdate(PlayerModelUpdateEvent event) {
String modelID = event.getModelID();
// 玩家模型已更新
}
```
---
## 插件事件
URL: https://wiki.arcartx.com/docs/server_api/15_events/9_plugin
## 插件事件
- ArcartX插件自身生命周期相关的事件。
## `ArcartXReloadEvent`
- ArcartX插件重载时触发(通过 `arcartx reload` 指令或API调用)
- **属性**:无
- **可取消**:否
- **调用示例**
```java
@EventHandler
public void onReload(ArcartXReloadEvent event) {
// ArcartX已重载,重新加载依赖ArcartX配置的内容
reloadMyConfig();
}
```
如果你的插件缓存了ArcartX的配置数据(如区域、UI等),建议监听此事件并在触发时刷新缓存。
---
## 事件概述
URL: https://wiki.arcartx.com/docs/server_api/15_events
## 事件系统
- 所有事件位于 `priv.seventeen.artist.arcartx.event` 包下,按功能分为三大类:
| 分类 | 包路径 | 说明 |
|-------|----------------|---------------------------|
| 客户端事件 | `event.client` | 由客户端行为触发,如按键、UI操作、实体视野变化等 |
| 玩家事件 | `event.player` | 由服务端玩家状态变化触发,如进出区域、模型更新等 |
| 插件事件 | `event.plugin` | 由ArcartX插件自身触发,如重载事件 |
## 监听示例
```java
@EventHandler
public void onClientKey(ClientKeyPressEvent event) {
Player player = event.getPlayer();
String key = event.getKeyName();
// 处理按键事件
}
```
大部分事件不可取消。可取消的事件会在各自的文档页面中标注。
---
## 导论
URL: https://wiki.arcartx.com/docs/shimmer/1_base/info
Shimmer脚本系统————轻量级的UI和动画脚本解决方案
## Shimmer是什么?
我在开发UI和动作控制器的过程中,曾尝试过很多方案,比如JS、Jython(Python解释器嵌入JAVA)、Molang等。
然而,以上方案更像是将"运算"嵌入到我们的整体运行中,或许是我钻研不精,没发掘到以上方式的最优方案来完成类似"嵌入"的操作。
其次,并不是每个服主都精通JS等脚本语言,有时候一两行表达式就能实现的功能,没必要为此去专门学习一门语言。所以我希望能做出一个半天内就能上手的方案。
同时,考虑到有些服主已经具备脚本编程基础,我们的语法设计也照顾到了这点,让有基础的使用者能更快上手。
最后,Shimmer这个项目诞生了,它翻译为"微光",就像微光一样,不需要太强烈的光源,但能够恰到好处地完成任务。
## 设计理念
参考了js、kotlin、python的优点,努力实现"刚刚好"的语法平衡
* 够用的语法糖:该简化的地方适度简化
* 直观的表达:避免过度语法糖带来的理解负担
* 保持精简:遵循"KISS"原则,减少学习压力
Shimmer从设计之初就定位为"为载体服务"的嵌入式脚本语言(针对特定场景优化的领域特定语言(DSL)),而非独立运行的通用语言
## "载体"的概念
Shimmer的核心设计围绕着"载体"概念展开,这是理解整个系统的关键
- 在UI或动画这些场景里,很多东西都是有层级关系的。
- 比如一个UI界面(载体),里面有几个面板(子载体),面板里又有一些按钮(孙载体)。
- Shimmer上下文的设计是围绕这种层级关系,在上下关系中,可以相互访问、调用。
### 载体能力
可以定义载体的各种属性,如组件标题、动作节点速度等
支持定义外部行为(如点击事件)和内部行为
内置14+种动画曲线,包括:
* 线性插值
* 贝塞尔曲线
* 圆周运动
* ...
---
Shimmer将持续更新完善,欢迎在使用过程中提供建议和反馈
---
## Shimmer开发者文档
URL: https://wiki.arcartx.com/docs/shimmer/api/api
API其实也就是怎么注册`对象`和`工具集函数`
## 工具集函数
~~~java
package priv.seventeen.artist.arcartx.shimmer.callable.function;
/**
* @program: ShimmerForArcartX
* @description: 输出
* @author: 17Artist
* @create: 2024-11-20 00:55
**/
@ShimmerNamespace("Shimmer")
public class ShimmerFunctions {
@ShimmerInvokeHandler("print")
public static void print(InvocationData invocationData){
System.out.println(invocationData.get(0).stringValue());
}
@ShimmerInvokeHandler("println")
public static void println(InvocationData invocationData){
for(IValue> value : invocationData.getArgs()){
System.out.println(value.stringValue());
}
}
}
~~~
- 既然是开发者文档我就不写那么多了,值得注意的是`@ShimmerInvokeHandler`所注解的函数参数应该只有一个`InvocationData`
- 至于这个`InvocationData`有什么函数,直接导包就能查看,无非是获取指定位数的参数,然后再根据你所求去取类型。
## 对象
```java
package priv.seventeen.artist.arcartx.shimmer.callable.object;
/**
* @program: ShimmerForArcartX
* @description: uuid对象
* @author: 17Artist
* @create: 2024-11-20 12:52
**/
public class UUIDObject implements IShimmerObject {
private final UUID uuid;
@ShimmerObjectConstructor("UUID")
public UUIDObject(InvocationData invocationData){
if(invocationData.size() >= 1){
UUID temp;
try{
temp = UUID.fromString(invocationData.get(0).stringValue());
} catch (Exception e){
temp = UUID.randomUUID();
}
this.uuid = temp;
} else {
uuid = UUID.randomUUID();
}
}
@Override
public String stringValue() {
return uuid.toString();
}
@Override
public String getTypeName() {
return "uuid";
}
@ShimmerInvokeHandler("getMostSignificantBits")
public long getMostSignificantBits(InvocationData data) {
return uuid.getMostSignificantBits();
}
@ShimmerInvokeHandler("getLeastSignificantBits")
public long getLeastSignificantBits(InvocationData data) {
return uuid.getLeastSignificantBits();
}
@ShimmerInvokeHandler("version")
public int version(InvocationData data) {
return uuid.version();
}
@ShimmerInvokeHandler("variant")
public int variant(InvocationData data) {
return uuid.variant();
}
}
```
- 怎么样,是不是特别简单,`构造器`通过`@ShimmerObjectConstructor`注解,参数应该只有一个`InvocationData`
- 至于函数,和上面工具集函数是一致的。
## 将你注册的函数导入到`ShimmerRuntime`
```java
package priv.seventeen.artist.arcartx.shimmer;
/**
* @program: ShimmerForArcartX
* @description: 示例
* @author: 17Artist
* @create: 2024-12-07 04:28
**/
public class EG {
public static void register(){
// 注册函数
CallableManager.INSTANCE.registerStaticFunction(MathFunctions.class);
// 注册对象
CallableManager.INSTANCE.registerShimmerObject(UUIDObject.class);
}
}
```
---
## item:物品编辑
URL: https://wiki.arcartx.com/docs/core/1_base/5_command/10_item
## 物品编辑指令
- 用于编辑手持物品的各种属性,所有子命令都需要手持物品执行。
### `arcartx item addTag`
- 为手持物品添加NBT标签
| 属性 | 值 |
|-----|-------------------------------------|
| 用法 | `arcartx item addTag ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `key`:NBT键名
- `value`:NBT值
### `arcartx item addLore`
- 为手持物品追加一行Lore
| 属性 | 值 |
|-----|-----------------------------------|
| 用法 | `arcartx item addLore ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `lore`:Lore文本,支持颜色代码
### `arcartx item setLore`
- 设置手持物品指定行的Lore
| 属性 | 值 |
|-----|--------------------------------------|
| 用法 | `arcartx item setLore ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `lore`:Lore文本
- `line`:行号(从0开始)
### `arcartx item insertLore`
- 在手持物品指定行插入Lore
| 属性 | 值 |
|-----|-----------------------------------------|
| 用法 | `arcartx item insertLore ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `lore`:Lore文本
- `line`:插入位置行号
### `arcartx item removeLore`
- 删除手持物品指定行的Lore
| 属性 | 值 |
|-----|-----------------------------------|
| 用法 | `arcartx item removeLore ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `line`:要删除的行号
### `arcartx item setDisplayName`
- 设置手持物品的显示名称
| 属性 | 值 |
|-----|--------------------------------------|
| 用法 | `arcartx item setDisplayName ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `name`:显示名称,支持颜色代码
### `arcartx item setIcon`
- 设置手持物品的图标贴图
| 属性 | 值 |
|-----|-----------------------------------|
| 用法 | `arcartx item setIcon ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `path`:图标资源路径
### `arcartx item setModel`
- 设置手持物品的模型
| 属性 | 值 |
|-----|-----------------------------------|
| 用法 | `arcartx item setModel ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `modelID`:模型ID
### `arcartx item setFPModel`
- 设置手持物品的第一人称模型
| 属性 | 值 |
|-----|-------------------------------------|
| 用法 | `arcartx item setFPModel ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `modelID`:第一人称模型ID
### `arcartx item setExtraModel`
- 设置手持物品的额外渲染模型
| 属性 | 值 |
|-----|--------------------------------------------------|
| 用法 | `arcartx item setExtraModel ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `locator`:定位器名称
- `modelID`:模型ID
### `arcartx item setUrl`
- 设置手持物品在界面中显示的贴图
| 属性 | 值 |
|-----|-----------------------------------|
| 用法 | `arcartx item setUrl ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `path`:贴图资源路径
### `arcartx item setDrop`
- 设置手持物品的掉落附加模型
| 属性 | 值 |
|-----|-----------------------------------|
| 用法 | `arcartx item setDrop ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `modelID`:掉落模型ID
### `arcartx item setCoolDownTag`
- 设置手持物品的冷却标签
| 属性 | 值 |
|-----|---------------------------------------|
| 用法 | `arcartx item setCoolDownTag ` |
| 权限 | `arcartx.command.admin.item.edit` |
| 执行者 | 仅玩家 |
- `value`:冷却标签值,相同标签的物品共享冷却
---
## area:区域
URL: https://wiki.arcartx.com/docs/core/1_base/5_command/11_area
## 区域指令
- 用于获取区域编辑工具。
### `arcartx area tool`
- 获取区域编辑工具到背包中
| 属性 | 值 |
|-----|------------------------------|
| 用法 | `arcartx area tool` |
| 权限 | `arcartx.command.admin.area` |
| 执行者 | 仅玩家 |
- 获取到的工具是一根附魔木棍,使用方式如下:
- 左键/右键 — 选择区域两端对角
- ALT + 右键 — 删除区域
- ALT + 左键 — 取消选择
- Shift + 右键 — 创建区域
- Shift + 左键 — 编辑所在区域优先级
---
## waypoint:路标
URL: https://wiki.arcartx.com/docs/core/1_base/5_command/12_waypoint
## 路标指令
- 用于为玩家添加、删除和清除路标。
### `arcartx waypoint add`
- 为玩家添加一个路标
| 属性 | 值 |
|-----|----------------------------------------------------------------------|
| 用法 | `arcartx waypoint add [?player]` |
| 权限 | `arcartx.command.admin.waypoint` |
| 执行者 | 仅OP |
- `id`:路标唯一标识
- `title`:路标显示标题
- `configId`:路标配置ID
- `x` `y` `z`:路标坐标
- `player`:可选,指定目标玩家,不填则为自己
### `arcartx waypoint delete`
- 删除玩家的指定路标
| 属性 | 值 |
|-----|------------------------------------------|
| 用法 | `arcartx waypoint delete [?player]` |
| 权限 | `arcartx.command.admin.waypoint` |
| 执行者 | 仅OP |
- `id`:路标唯一标识
- `player`:可选,指定目标玩家,不填则为自己
### `arcartx waypoint clear`
- 清除玩家的所有路标
| 属性 | 值 |
|-----|------------------------------------|
| 用法 | `arcartx waypoint clear [?player]` |
| 权限 | `arcartx.command.admin.waypoint` |
| 执行者 | 仅OP |
- `player`:可选,指定目标玩家,不填则为自己
---
## parser:脚本执行
URL: https://wiki.arcartx.com/docs/core/1_base/5_command/13_parser
## 脚本执行指令
- 用于在玩家客户端远程执行Shimmer脚本代码。
| 属性 | 值 |
|-----|------------------------------------------|
| 用法 | `arcartx parser ` |
| 权限 | `arcartx.command.admin.parser` |
| 执行者 | 仅OP |
- `player`:目标玩家名
- `code`:要执行的Shimmer脚本代码
- `async`:是否异步执行(布尔值)
---
## crc64:资源校验
URL: https://wiki.arcartx.com/docs/core/1_base/5_command/14_crc64
## 资源校验指令
- 用于更新客户端拓展的CRC64校验列表,确保客户端资源完整性。
### `arcartx crc64 update`
- 从当前玩家客户端获取CRC64校验列表并更新到服务端配置
| 属性 | 值 |
|-----|-------------------------------|
| 用法 | `arcartx crc64 update` |
| 权限 | `arcartx.command.admin.crc64` |
| 执行者 | 仅玩家 |
- 执行后会将你客户端的CRC64校验值同步到服务端配置文件中。
---
## resourceSync:资源同步
URL: https://wiki.arcartx.com/docs/core/1_base/5_command/15_resourcesync
## 资源同步指令
- 用于从后端服务同步文件校验信息。
### `arcartx resourceSync update`
- 从后端同步文件校验信息到服务端
| 属性 | 值 |
|-----|----------------------------------|
| 用法 | `arcartx resourceSync update` |
| 权限 | `arcartx.command.admin.resource` |
| 执行者 | 仅OP |
- 执行后会异步请求后端服务,同步完成后会提示更新的文件数量。
- 需要在配置中启用资源客户端功能才能使用。
---
## adyeshach:Adyeshach集成
URL: https://wiki.arcartx.com/docs/core/1_base/5_command/16_adyeshach
## Adyeshach指令
- 用于为Adyeshach创建的NPC实体设置ArcartX模型和碰撞体积。
- 需要服务端安装Adyeshach插件。
### `arcartx adyeshach setModel`
- 为就近的Adyeshach单位设置模型
| 属性 | 值 |
|-----|------------------------------------------------|
| 用法 | `arcartx adyeshach setModel ` |
| 权限 | `arcartx.command.admin.adyeshach` |
| 执行者 | 仅玩家 |
- `modelID`:模型ID
- `scale`:模型缩放比例
### `arcartx adyeshach setBox`
- 为就近的Adyeshach单位设置碰撞体积
| 属性 | 值 |
|-----|---------------------------------------------|
| 用法 | `arcartx adyeshach setBox ` |
| 权限 | `arcartx.command.admin.adyeshach` |
| 执行者 | 仅玩家 |
- `width`:碰撞箱宽度
- `height`:碰撞箱高度
---
## reload:重载
URL: https://wiki.arcartx.com/docs/core/1_base/5_command/1_reload
## 重载插件
- 用于重载ArcartX的所有配置文件,是你日常使用中最常用的指令。
| 属性 | 值 |
|-----|----------------------------------|
| 用法 | `arcartx reload [?withResource]` |
| 权限 | `arcartx.command.reload` |
| 执行者 | 仅OP |
- `withResource`:可选参数,布尔值。设为 `true` 时会连同客户端资源文件一起重载,默认仅重载服务端配置。
- 示例:
- `arcartx reload` — 仅重载服务端配置
- `arcartx reload true` — 同时重载客户端资源
- 也可以在游戏内通过快捷键 `Alt + R` 触发 `arcartx reload true`,效果等同于同时重载服务端配置和客户端资源。
---
## model:模型
URL: https://wiki.arcartx.com/docs/core/1_base/5_command/2_model
## 模型指令
- 用于调试和测试模型相关功能,包括设置模型、播放动画、控制器等。
### `arcartx model setModel`
- 设置玩家模型
| 属性 | 值 |
|-----|-----------------------------------------------------|
| 用法 | `arcartx model setModel ` |
| 权限 | `arcartx.command.admin.entity.edit` |
| 执行者 | 仅OP |
- `player`:目标玩家名
- `modelID`:模型ID
- `scale`:模型缩放比例
### `arcartx model removeModel`
- 移除玩家模型
| 属性 | 值 |
|-----|--------------------------------------|
| 用法 | `arcartx model removeModel ` |
| 权限 | `arcartx.command.admin.entity.edit` |
| 执行者 | 仅OP |
- `player`:目标玩家名
### `arcartx model testController`
- 测试为玩家设置动作控制器
| 属性 | 值 |
|-----|--------------------------------------------------------|
| 用法 | `arcartx model testController ` |
| 权限 | `arcartx.command.admin.entity.edit` |
| 执行者 | 仅OP |
- `player`:目标玩家名
- `controllerID`:控制器配置ID
### `arcartx model testControllerState`
- 测试设置动作控制器的状态
| 属性 | 值 |
|-----|--------------------------------------------------------------------------------|
| 用法 | `arcartx model testControllerState ` |
| 权限 | `arcartx.command.admin.entity.edit` |
| 执行者 | 仅OP |
- `player`:目标玩家名
- `subControllerID`:子控制器ID
- `state`:状态名称
- `speed`:播放速度
### `arcartx model testAddExtraModel`
- 测试为玩家添加额外模型
| 属性 | 值 |
|-----|--------------------------------------------------------------------|
| 用法 | `arcartx model testAddExtraModel ` |
| 权限 | `arcartx.command.admin.entity.edit` |
| 执行者 | 仅OP |
- `player`:目标玩家名
- `locatorName`:定位器名称
- `modelID`:模型ID
### `arcartx model testRemoveModel`
- 测试移除玩家的额外模型
| 属性 | 值 |
|-----|--------------------------------------------------------|
| 用法 | `arcartx model testRemoveModel ` |
| 权限 | `arcartx.command.admin.entity.edit` |
| 执行者 | 仅OP |
- `player`:目标玩家名
- `locatorName`:定位器名称
### `arcartx model testSubstitutionModel`
- 测试为玩家设置覆盖模型
| 属性 | 值 |
|-----|-----------------------------------------------------------------|
| 用法 | `arcartx model testSubstitutionModel ` |
| 权限 | `arcartx.command.admin.entity.edit` |
| 执行者 | 仅OP |
- `player`:目标玩家名
- `modelID`:覆盖模型ID
- `mode`:布尔值,`true` 为传统隐藏模式,`false` 为完整替换模式
### `arcartx model testAnimation`
- 测试为玩家播放动画
| 属性 | 值 |
|-----|--------------------------------------------------------------|
| 用法 | `arcartx model testAnimation ` |
| 权限 | `arcartx.command.admin.entity.edit` |
| 执行者 | 仅OP |
- `player`:目标玩家名
- `animationID`:动画ID
- `speed`:播放速度
### `arcartx model testFPAnimationByCount`
- 测试为玩家播放第一人称动画(按次数)
| 属性 | 值 |
|-----|-------------------------------------------------------------------------------|
| 用法 | `arcartx model testFPAnimationByCount ` |
| 权限 | `arcartx.command.admin.entity.edit` |
| 执行者 | 仅OP |
- `player`:目标玩家名
- `animationID`:动画ID
- `speed`:播放速度
- `count`:播放次数
### `arcartx model testFPAnimationByTime`
- 测试为玩家播放第一人称动画(按持续时间)
| 属性 | 值 |
|-----|-----------------------------------------------------------------------------|
| 用法 | `arcartx model testFPAnimationByTime