- 版权类型
- 二次开发
- 插件中文名称
- 语音聊天扩展
- 插件英文名称
- VoiceChatPlus
- 支持的核心(服务端)
- Paper
- Leaves
- 语言支持
- 多语言
- 前置组件
- simple voice chat:https://www.minebbs.com/resources/simple-voice-chat.10309/
PAPI:https://www.minebbs.com/resources/placeholderapi.8229/
- 适配版本(Java)
- 1.21
- 1.20
- 1.19
[MD]
> **🎤 VoiceChatPlus v1.0.0** — Simple Voice Chat 附属插件 · 语音组管理增强
>
> 🖥️ 全 GUI 化 · 💬 聊天交互 · 🗳️ 入组审批 · 📶 PAPI 占位符 · 🛡️ 命令屏蔽
---
## ✨ 功能一览
| 领域 | 能力 | 说明 |
|:---:|:---|:---|
| 🖥️ **全 GUI 化** | 玩家选择全部可视化 | 带玩家头颅的箱子菜单 + 聊天输入拦截,告别记名字 |
| 💬 **聊天 TUI** | `/vcp menu` | 组列表每行显示类型/人数/组长,组名可点击申请 |
| 🗳️ **入组审批** | 3 种模式 | 投票 / 任意成员审批 / 仅组长审批 |
| 📶 **PAPI 占位符** | 5 个 | 状态 · 组名 · 组规模 · 组长 · 成员列表 |
| 🛡️ **命令屏蔽** | 静默接管 `/voicechat` | 拦截执行 + 隐藏 Tab 补全,表现如从未注册 |
| 🎨 **外观自定义** | `gui.yml` 全可配 | 材质 / 填充 / 装饰 / 槽位 / 内联 PAPI |
| 🌐 **多语言** | 热重载 | zh_CN / en_US,旧文件不覆盖 |
---
## 🗺️ 玩家选择全 GUI 化
所有玩家选择都变成**带玩家头颅的箱子菜单**——不再需要记 ID:
```
🗃️ 主菜单
├── 👤 邀请成员 ──▶ 点击玩家头颅 ──▶ ✉️ 发送邀请(该玩家从列表消失)
├── 📨 待处理申请 ──▶ 点击申请者头颅 ──▶ 🗳️ 动作页[同意/拒绝] ──▶ 列表自动刷新
└── 💌 邀请我 ──▶ 点击邀请者头颅 ──▶ ✅ 加入组 · 列表消失
```
- 每个申请人/邀请人都是**玩家头颅**,悬浮即见玩家名
- 输入组名、密码时**消息不广播**,只有自己看到反馈
- 投票项 lore 实时显示 `入组投票: 已同意/已拒绝/未投`
- 重复点击已投投票项 → `你已投过票`
## 📥 安装
1. 安装 **Simple Voice Chat**(bukkit 版,**须先加载**)
2. 安装 **PlaceholderAPI**(可选,增强显示)
3. 将 `VoiceChatPlus-1.0.0.jar` 放入 `plugins/` 并重启
4. 玩家输入 `/vcp` 🎉
> 🟢 启动日志出现 `========== VoiceChatPlus v1.0.0 已启用 ==========` 即成功
> 🔴 若出现 `未找到 Simple Voice Chat 服务` → SVC 版本不兼容或加载时序问题
---
## ⌨️ 命令速查
### 🖥️ 界面类
| 命令 | 说明 |
|:---|:---|
| `/vcp` | 打开 9 格箱子主界面(默认) |
| `/vcp gui` | 强制打开箱子界面 |
| `/vcp menu` | 聊天菜单(组列表可点击) |
| `/vcp group` | 查看我的语音组 |
| `/vcp help` | 显示帮助 |
### ⚙️ 组操作类
| 命令 | 说明 |
|:---|:---|
| `/vcp create <名称>` | 创建语音组 |
| `/vcp join <组名>` | 申请入组(OPEN 组直接加入) |
| `/vcp leave` | 退出当前组 |
| `/vcp invite <玩家>` | 邀请玩家(可点击接受/拒绝) |
| `/vcp accept` / `/vcp decline` | 接受 / 拒绝邀请 |
| `/vcp vote <y\|n>` | 对入组投票投赞成 / 反对 |
### 👑 组长类
| 命令 | 说明 |
|:---|:---|
| `/vcp kick <玩家>` | 移出成员 |
| `/vcp rename <新名>` | 重命名组 |
| `/vcp pass [密码]` | 设置 / 清除入组密码 |
| `/vcp type <OPEN\|NORMAL>` | 切换组类型 |
| `/vcp disband` | 解散组 |
### 🛠️ 管理类
| 命令 | 说明 |
|:---|:---|
| `/vcp reload` | 热重载配置 / 语言 / GUI 外观 |
---
## 📊 PAPI 占位符
| 占位符 | 含义 | 示例 |
|:---|:---|:---|
| `%voicechatplus_status%` | 语音是否在线 | 🟢 `在线` / ⚫ `离线` |
| `%voicechatplus_group%` | 当前语音组 | `小队` / `无组` |
| `%voicechatplus_group_size%` | 组内在线成员数 | `3` / `0` |
| `%voicechatplus_leader%` | 组长名 | `KDklin` / `无` |
| `%voicechatplus_members%` | 成员列表 | `KDklin, Steve` |
> 占位符可嵌入 `gui.yml` 的 item 名称/描述,GUI 内直接渲染真实值。
---
## 📐 审批模式
| 模式 | 谁能通过申请 | 适用场景 |
|:---|:---|:---|
| `VOTE` | 按 `vote.rule` 投票 | 中小团队 |
| `APPROVE` | 组内任意成员 | 熟人开黑 |
| `LEADER` | 仅组长 | 严格管理 |
**VOTE 规则(vote.rule):**
| 规则 | 判定 |
|:---|:---|
| `MAJORITY_ONLINE` | 同意 ≥ 在线成员半数 |
| `MAJORITY_CAST` | 赞成多于反对 |
| `UNANIMOUS` | 全体一致同意 |
| 数字 | 固定同意票数 |
---
## ⚙️ 完整配置(config.yml)
> 首次启动自动生成于 `plugins/VoiceChatPlus/config.yml`,以下为全部默认值:
```yaml
# VoiceChatPlus 配置文件
# 语言文件选择:对应 lang/ 目录下的文件名(不含 .yml)
language: zh_CN
# PAPI 占位符显示文本
placeholders:
# %voicechatplus_status% — 语音是否可用
status:
available: "&a在线"
unavailable: "&7离线"
# %voicechatplus_group% — 当前语音组
group:
none: "&7无组"
# %voicechatplus_group_size% — 组内在线成员数
group_size:
zero: "&70"
# %voicechatplus_leader% — 组长名
leader:
none: "&7无"
# %voicechatplus_members% — 成员列表
members:
separator: "&7, &f"
none: "&7无"
# 入组审批模式: VOTE(投票) | APPROVE(任意成员审批) | LEADER(仅组长审批)
join-request-mode: VOTE
vote:
# MAJORITY_ONLINE(同意>=在线成员半数) | MAJORITY_CAST(赞成多于反对)
# | UNANIMOUS(全体一致同意) | 数字(固定同意票数)
rule: MAJORITY_ONLINE
timeout-seconds: 60
gui:
default-open: true # /vcp 默认打开 GUI(true)还是聊天菜单(false)
```
---
## 🎛️ 完整 GUI 外观配置(gui.yml)
> 所有 name/lore/title/material **均支持占位符**。`material` 填 Bukkit Material 枚举名(1.13+ 全版本可用)。槽位与点击动作由插件内置,不可配置。
```yaml
# VoiceChatPlus 箱子 GUI 外观配置
# 所有 name/lore/title/material 均支持占位符:
# 内置: %player% %group% %type% %type-material% %size% %leader% %status%
# 装了 PlaceholderAPI 时还支持全部 PAPI 占位符(如 %voicechatplus_status%)
# material 填 Bukkit Material 枚举名(1.13+ 全版本可用)
# 槽位与点击动作由插件内置,不可配置。
main:
title: "&8语音组管理"
fill-material: GRAY_STAINED_GLASS_PANE # 空位填充物(留空 "" = 不填充)
decorations: [] # 指定槽位装饰:[{slot: 9, material: X, name: " ", lore: []}]
items:
group-list: { material: EMERALD, name: "&6语音组列表", lore: ["&7查看所有语音组并申请加入"] }
my-group: { material: NAME_TAG, name: "&b我的语音组", lore: ["&7查看自己所在组"] }
pending: { material: BOOK, name: "&e待处理申请", lore: ["&7审批组内成员的入组申请/投票"] }
invites: { material: PAPER, name: "&d邀请我", lore: ["&7查看别人邀请你加入的组"] }
help: { material: KNOWLEDGE_BOOK, name: "&7帮助", lore: ["&7在聊天框显示帮助"] }
group-list:
title: "&8语音组列表"
fill-material: ""
decorations: []
items:
group-item:
material: "%type-material%"
name: "&f%group%"
lore:
- "&7类型: &b%type%"
- "&7在线: &a%size% &7/ 组长: &e%leader%"
- "&7点击查看详情"
prev-page: { material: ARROW, name: "&7上一页" }
next-page: { material: ARROW, name: "&7下一页" }
group-detail:
title: "&8语音组详情"
fill-material: ""
decorations: []
items:
detail:
material: "%type-material%"
name: "&f%group%"
lore:
- "&7类型: &b%type%"
- "&7在线: &a%size% &7/ 组长: &e%leader%"
back: { material: ARROW, name: "&7返回" }
actions:
leave: { material: OAK_DOOR, name: "&c离开本组", lore: ["&7退出当前语音组"] }
invite: { material: NAME_TAG, name: "&d邀请成员", lore: ["&7邀请在线玩家加入本组"] }
kick: { material: PLAYER_HEAD, name: "&c踢人", lore: ["&7将成员移出本组(点击后选人)"] }
rename: { material: ANVIL, name: "&6改名", lore: ["&7修改组名"] }
type: { material: ENDER_PEARL, name: "&b改组类型", lore: ["&7切换 NORMAL/OPEN/ISOLATED"] }
password: { material: TRIPWIRE_HOOK, name: "&9设置密码", lore: ["&7设置或清除组密码"] }
disband: { material: BARRIER, name: "&4解散本组", lore: ["&7移除所有成员并解散组"] }
join-open: { material: LIME_DYE, name: "&a直接加入", lore: ["&7这是一个开放组,点击直接加入"] }
join-request: { material: BOOK, name: "&e申请加入", lore: ["&7发送入组申请给组内成员"] }
invite-picker:
title: "&8邀请玩家"
fill-material: ""
decorations: []
items:
head:
material: PLAYER_HEAD
name: "&f%player%"
lore:
- "&7点击邀请加入你的组"
prev-page: { material: ARROW, name: "&7上一页" }
next-page: { material: ARROW, name: "&7下一页" }
back: { material: ARROW, name: "&7返回" }
pending:
title: "&8待处理申请"
fill-material: ""
decorations: []
items:
head:
material: PLAYER_HEAD
name: "&f%player%"
lore:
- "&7点击处理入组申请"
head-vote:
material: PLAYER_HEAD
name: "&f%player%"
lore:
- "&7入组投票: %vote-status%"
- "&7点击投票"
prev-page: { material: ARROW, name: "&7上一页" }
next-page: { material: ARROW, name: "&7下一页" }
back: { material: ARROW, name: "&7返回" }
action:
title: "&8处理请求"
fill-material: ""
decorations: []
items:
head: { material: PLAYER_HEAD, name: "&f%player%", lore: [] }
approve: { material: LIME_DYE, name: "&a同意", lore: ["&7同意该玩家加入"] }
deny: { material: RED_DYE, name: "&c拒绝", lore: ["&7拒绝该玩家加入"] }
vote-yes: { material: LIME_DYE, name: "&a投同意", lore: ["&7投下同意票"] }
vote-no: { material: RED_DYE, name: "&c投反对", lore: ["&7投下反对票"] }
accept: { material: LIME_DYE, name: "&a接受", lore: ["&7接受邀请加入"] }
decline: { material: RED_DYE, name: "&c拒绝", lore: ["&7拒绝该邀请"] }
back: { material: ARROW, name: "&7返回" }
member-list:
title: "&8组内成员(点击踢出)"
fill-material: ""
decorations: []
member-name: "&c%player%" # %player% = 成员名
member-lore: ["&7点击踢出该成员"]
```
---
## 📦 兼容性
| 服务器端 | Minecraft | SVC 版本 | 状态 |
|:---:|:---|:---|:---:|
| Paper / Leaves | 1.18.2 | **SVC 2.4.15** | ✅ |
| Paper / Leaves | 1.19 – 1.20 | SVC 2.4.x / 2.5.x | ✅ |
| Paper / Leaves | 1.21.x | SVC 2.5.x | ✅ |
| — | — | SVC ≤ 2.3.x | ❌ |
> ⚠️ voicechat-api ≥ 2.4.0 已实证兼容;SVC 2.3.x 及更老缺少 `Group.getType()` / `getGroups()` / `RemoveGroupEvent`。
## 🌐 语言文件
- 默认 `zh_CN`,支持 `en_US`,改 `config.yml` 的 `language` 后 `/vcp reload` 生效
- 插件**不会覆盖** `plugins/VoiceChatPlus/lang/` 中已存在的语言文件(保护自定义翻译)
- 升级后若界面出现 `{xxx}` 字样 → 删除 `lang/` 目录重启,重新从 jar 拷贝最新翻译
## 🔗 下载与链接
- 源码:https://github.com/LLKYTA/VoiceChatPlus
- Releases:https://github.com/LLKYTA/VoiceChatPlus/releases
- 反馈/建议:回帖即可
[/MD]