PlayTimeManager 玩家在线时长统计插件
PlayTimeManager
一款专为 Paper / Purpur 服务端设计的高性能玩家在线时长追踪与自动化奖励插件。支持全版本(1.19 – 26.2),内置 SQLite 存储、HikariCP 连接池、内存缓存、AFK 检测、目标系统、连续登录奖励、排行榜、LuckPerms 联动与 PlaceholderAPI 深度集成,并通过直观的 GUI 让管理员零代码搭建玩家成长体系。
作者:TheGaBr0(TheGabro)
许可证:GPL-3.0-or-later(免费、开源)
当前版本:v3.6.5
下载量:5000+
官网 / Wiki:wiki.playtimemanager.com
GitHub:github.com/TheGaBr0/PlayTimeManager
下载渠道:Modrinth / Hangar / SpigotMC
概述
PlayTimeManager(简称 PTM)解决的问题很明确:精准追踪每个玩家在服务器上的累计在线时长,并基于时长自动触发奖励、晋升、称号等互动机制。它不是简单地读取服务端自带的 stat.play_one_minute,而是在此基础上叠加独立的"人工时长"字段,支持管理员手动增减、跨版本迁移、防篡改校验,确保数据长期稳定。
核心优势
专为 Paper 优化:不再支持 Spigot,充分利用 Paper 的异步 API 与性能优势
双模式存储:默认 SQLite(零配置即用),可一键迁移至 MySQL / MariaDB / PostgreSQL
AFK 智能识别:原生支持 EssentialsX、Purpur 内置、AFKPlus、JetsAntiAFKPro,还可通过 PAPI 占位符对接任意 AFK 插件
两大奖励系统:Goals(时长目标) + Join Streak(连续登录),支持消息、命令、权限、声效、物品、GUI 图标六种奖励类型
完整 GUI 管理:目标创建、奖励配置、连续登录查看、统计面板全部图形化,无需手编 YAML
LuckPerms 联动:自动给达标玩家添加权限组、前缀,排行榜直接显示 LuckPerms 前缀
PlaceholderAPI 深度集成:20+ 内置占位符,支持嵌套占位符、自定义时间格式、离线玩家查询
隐身兼容:v3.6.5 新增 Vanish 隐身模式,隐身玩家不会通过 PTM 占位符或 GUI 泄露在线状态
自动更新与备份:升级时自动备份整个插件文件夹,配置文件自动迁移,数据向下兼容至 v3.0.4
高性能:内存缓存 + HikariCP 连接池 + 全异步数据库读写,对服务器 TPS 影响极低
版本与兼容性
支持的服务端与 MC 版本
| 服务端 | 最低 MC 版本 | 最高 MC 版本 | 备注 |
| :--- | :--- | :--- | :--- |
| Paper | 1.19 | 26.2 | 首选,性能最佳 |
| Purpur | 1.19 | 26.2 | 完全兼容,额外支持 Purpur AFK 检测 |
| Folia | 1.19 | 26.2 | 区域化线程调度兼容 |
⚠️ Spigot 已不再受支持。插件在 Spigot 上可能无法加载或运行不稳定,请迁移至 Paper 或 Purpur。
Java 版本要求
Java 17 或更高版本
依赖插件(可选)
| 插件 | 用途 | 是否必须 |
| :--- | :--- | :--- |
| PlaceholderAPI | 解锁全部 PAPI 占位符功能 | 推荐 |
| LuckPerms | 权限组自动晋升、前缀显示 | 推荐 |
| EssentialsX | AFK 检测数据源 | 可选 |
| AFKPlus | AFK 检测数据源 | 可选 |
| JetsAntiAFKPro | AFK 检测数据源 | 可选 |
| ProtocolLib | 部分 GUI 功能依赖 | 可选 |
离线模式 / 正版模式
两种模式均完全支持
离线模式玩家昵称大小写敏感
正版模式玩家昵称查找不区分大小写(v3.6.4+)
UUID 映射系统防止重复数据
核心功能详解
在线时长追踪
玩家首次加入时,自动从服务端内置统计 stat.play_one_minute 读取初始时长作为起点
之后所有增量由插件独立记录到数据库,与服务端统计解耦
支持人工时长(artificial playtime):管理员可手动 add / remove / set,不影响原始统计
总时长 = 服务端统计 + 人工增减,两者分开存储、合并展示
AFK 检测与过滤
支持四种 AFK 数据源,通过 config.yml 的 afk-detection-plugin 字段切换:
| 检测源 | 配置值 | 说明 |
| :--- | :--- | :--- |
| EssentialsX | essentialsx | 最成熟方案 |
| Purpur 内置 | purpur | 需 server.properties 中 player-idle-timeout > 0 且 purpur.yml 中 kick-if-idle: false |
| AFKPlus | afkplus | v3.6.5+ |
| JetsAntiAFKPro | jetsantiafkpro | v3.6.3+ |
| 通用 PAPI | none + afk-placeholder | 通过任意 PAPI 占位符(如 %essentials_afk%)判断 |
| 关闭 | none | 不检测 AFK |
开启 ignore-afk-time: true 后,AFK 时段不计入总时长、目标进度和排行榜。
Goals 目标系统
为每个玩家设定"达到 X 时长即奖励"的里程碑,全部通过 GUI 配置:
时间要求:可设为 none 或具体时长(支持 1y 30d 2h 10m 5s 格式)
权限要求:可要求玩家拥有指定权限节点或 LuckPerms 组
占位符条件:用 PAPI 占位符做布尔判断(如 %PTM_playtime% > 3600、%vault_eco_balance% >= 1000)
可重复:勾选后玩家可反复完成同一目标并重复领奖
离线奖励:开启后,离线期间达标者下次上线自动补发
调度方式:秒数间隔 或 Cron 表达式(重启后自动恢复)
Join Streak 连续登录奖励
玩家在可配置的时间窗口内连续加入服务器即可累积"连击天数":
时间窗口通过 Cron 表达式定义,不限于"每天",可以是每周、每 12 小时等任意节奏
支持循环奖励:达到设定天数后自动回到第 1 天重新开始
支持不可重复奖励:单次奖励仅发放一次
奖励消息支持延迟发送,避免与登录事件冲突
GUI 中可查看自己或他人的连击状态(只读)
奖励类型(Goals 与 Join Streak 共用)
| 类型 | 说明 |
| :--- | :--- |
| 执行命令 | 支持控制台命令或玩家命令,可使用 %PLAYER_NAME% 等占位符 |
| 发送消息 | 自定义聊天栏通知,支持十六进制颜色与 Legacy 颜色代码 |
| 播放声效 | 指定音效 ID,支持自定义音效 |
| 授予权限 | 临时或永久权限节点(需 LuckPerms) |
| 添加权限组 | 自动将玩家加入指定 LuckPerms 组 |
| 物品奖励 | GUI 图标对应的物品,支持 PLAYER_HEAD、附魔光效 |
排行榜系统
命令 /playtimetop 在聊天栏分页展示,可点击翻页
支持 LuckPerms 前缀显示(%PREFIX%)
支持将指定玩家从排行榜中隐藏(/playtimeattribute hidefromleaderboard)
PAPI 占位符 %PTM_playtime_top_% / %PTM_rank_% / %PTM_lp_prefix_top_% 可在任何支持 PAPI 的地方调用
统计 GUI(/playtimestats)
完全可定制的图形化统计面板,根据查看者权限自动切换三种视图:
| 视图 | 触发条件 | 显示内容 |
| :--- | :--- | :--- |
| Owner 视图 | 查看自己的数据 | 总时长、人工时长、AFK 时长、首次加入日期、最后在线、目标完成数 |
| Player 视图 | 查看他人数据 | 基础公开信息 |
| Staff 视图 | 拥有 playtime.others.stats.staff | 全部字段 + 数据库原始数据 |
自定义时间格式
在 Customization/PlaytimeFormats/ 目录下创建 YAML 文件,定义自己的时间显示格式:
支持自动隐藏零值单位
支持单复数自动切换(如 1 day / 2 days)
支持 Legacy 颜色(&6)与十六进制颜色(&#FF5500)
可在 PAPI 占位符后追加格式名,如 %PTM_playtime:custom%
Vanish 隐身模式(v3.6.5+)
开启后,隐身玩家的在线状态不会通过 PTM 的 PAPI 占位符泄露
/playtimestats GUI 中对隐身玩家自动隐藏
控制台、有权限的管理员、玩家本人仍可见真实数据
数据库迁移系统(v3.6.3+)
支持在 SQLite / MySQL / MariaDB / PostgreSQL 之间无缝切换:
/playtimemigration start
/playtimemigration status
/playtimemigration cancel
迁移在下次重启时自动执行,执行前自动备份全部数据。
命令列表
玩家命令
| 命令 | 别名 | 说明 | 默认权限 |
| :--- | :--- | :--- | :--- |
| /playtime | — | 查看自己的在线时长 | 所有玩家 |
| /playtime | — | 查看指定玩家的在线时长 | playtime.others |
| /playtimetop [数量] | /pttop | 查看在线时长排行榜(默认 100 名) | 所有玩家 |
| /playtimeaverage | /ptavg | 查看全服平均在线时长 | 所有玩家 |
| /playtimepercentage [玩家] [时长] | /ptpercent | 查看某玩家时长占全服平均的百分比 | 所有玩家 |
| /playtimestats [玩家] | /ptstats | 打开统计 GUI | playtime.stats |
| /playtimegoal | /ptgoal | 打开目标管理 GUI | playtime.goal |
| /playtimejoinstreak | /ptjsk | 打开连续登录奖励 GUI | playtime.joinstreak |
| /playtimejoinstreak seeplayer | — | 以只读方式查看他人的连击奖励 | playtime.joinstreak.seeplayer |
| /claimrewards | — | 打开可领取奖励的 GUI | playtime.joinstreak.claim |
管理员命令
| 命令 | 别名 | 说明 | 权限 |
| :--- | :--- | :--- | :--- |
| /playtime add | — | 增加玩家在线时长 | playtime.others.modify |
| /playtime remove | — | 减少玩家在线时长 | playtime.others.modify |
| /playtime set | — | 设置玩家在线时长为指定值 | playtime.others.modify |
| /playtime reset | — | 重置玩家数据(类型:all/db/stats/server_playtime/playtime/last_seen/first_join/joinstreak/joinstreak_rewards/goals/everything) | playtime.others.modify |
| /playtime backup | /ptbkp | 手动触发数据库备份 | playtime.backup |
| /playtimegoal checknow | — | 立即触发指定目标的完成检查 | playtime.goal.checknow |
| /playtimegoal rename | — | 重命名目标 | playtime.goal.rename |
| /playtimejoinstreak set | — | 设置玩家的相对连击数 | playtime.joinstreak.set |
| /playtimeattribute hidefromleaderboard | /ptattr | 将玩家从排行榜隐藏或恢复 | playtime.others.attributes |
| /playtimereload | /ptreload | 重载插件配置 | playtime.admin.reload |
| /playtimemigration start | — | 开始数据库迁移(控制台 only) | 控制台 |
| /playtimemigration status | — | 查看迁移状态 | 控制台 |
| /playtimemigration cancel | — | 取消待执行的迁移 | 控制台 |
时长格式说明
所有接受时长的命令均支持多单位混合输入:
/playtime add Steve 1y 30d 2h 10m 5s
/playtime set Alex 500m
/playtime remove Bob 1d12h
可用单位:s(秒)、m(分)、h(时)、d(天)、w(周)、mo(月,默认 30 天)、y(年)、mc(MC 天,1 MC 天 = 20 分钟)
PlaceholderAPI 占位符完整列表
基础时长
| 占位符 | 说明 |
| :--- | :--- |
| %PTM_playtime% | 当前玩家的格式化总时长 |
| %PTM_playtime_% | 指定玩家的格式化总时长 |
| %PTM_playtime_#% | 排行榜第 # 名玩家的时长 |
| %PTM_afk_playtime% | 当前玩家的 AFK 时长 |
| %PTM_afk_playtime_% | 指定玩家的 AFK 时长 |
| %PTM_afk_playtime_#% | 排行榜第 # 名的 AFK 时长 |
时间单位转换
在占位符末尾追加 _s / _m / _h / _d / _w / _mo / _y 可获取对应单位的数值:
%PTM_playtime_h% -> 当前玩家的小时数
%PTM_playtime_d% -> 当前玩家的天数
%PTM_lastseen_elapsed_m% -> 距最后在线多少分钟
排行榜相关
| 占位符 | 说明 |
| :--- | :--- |
| %PTM_rank% | 当前玩家的排行榜名次 |
| %PTM_rank_% | 指定玩家的排行榜名次 |
| %PTM_playtime_top_% | 排行榜第 # 名玩家的时长 |
| %PTM_nickname_top_% | 排行榜第 # 名玩家的昵称 |
| %PTM_lp_prefix_top_% | 排行榜第 # 名玩家的 LuckPerms 前缀 |
| %PTM_lastseen_top_% | 排行榜第 # 名玩家的最后在线日期 |
| %PTM_lastseen_elapsed_top_% | 距排行榜第 # 名最后在线多久 |
日期与连击
| 占位符 | 说明 |
| :--- | :--- |
| %PTM_firstjoin% | 当前玩家的首次加入日期 |
| %PTM_firstjoin_% | 指定玩家的首次加入日期 |
| %PTM_lastseen% | 当前玩家的最后在线日期 |
| %PTM_lastseen_elapsed% | 距当前玩家最后在线多久 |
| %PTM_joinstreak% | 当前玩家的连续登录天数 |
| %PTM_joinstreak_% | 指定玩家的连续登录天数 |
目标与奖励状态
| 占位符 | 说明 |
| :--- | :--- |
| %PTM_goal_completed_% | 当前玩家是否完成指定目标 |
| %PTM_goal_completed_count% | 当前玩家已完成的目标总数 |
| %PTM_goal_completed_count_% | 指定玩家已完成的目标总数 |
| %PTM_reward_status_% | 奖励状态(pending/claimed/expired) |
| %PTM_reward_repeatable_% | 奖励是否可重复领取 |
嵌套占位符(v3.6.5+)
PTM 占位符可接收另一个 PAPI 占位符作为参数:
%PTM_rank_%player_name%% -> 用 PAPI Player 扩展解析出的玩家名的排行
%PTM_playtime_%vault_eco_balance%% -> 结合经济数据做条件判断
自定义时间格式
在 Customization/PlaytimeFormats/ 创建 YAML 后,通过冒号追加格式名调用:
%PTM_playtime:myformat%
%PTM_playtime_:myformat%
配置文件说明
目录结构
plugins/PlayTimeManager/
├── config.yml # 主配置文件
├── Customization/
│ ├── Commands/
│ │ └── commands-config.yml # 命令输出文本翻译
│ ├── GUIs/
│ │ └── GUIs-config.yml # 所有 GUI 的布局与文本
│ └── PlaytimeFormats/
│ └── default.yml # 自定义时间格式
├── Goals/ # 每个目标一个 YAML 文件
│ ├── 10h-reward.yml
│ └── daily-login.yml
├── JoinStreaks/ # 每个连击奖励一个 YAML 文件
│ └── 7day-streak.yml
└── PlayTimeManager.db # SQLite 数据库文件
config.yml 关键字段
---- 基础设置 ----
prefix: "&8[&bPTM&8] &r" # 插件所有消息的前缀
datetime-format: "dd/MM/yyyy HH:mm" # 日期显示格式
month-value-in-days: 30 # 1 个月等于多少天(用于 mo 单位)
---- 消息定制 ----
playtime-self-message: "&a你的在线时长: &6%PLAYTIME%"
playtime-others-message: "&a%PREFIX%%PLAYER_NAME%&a的在线时长: &6%PLAYTIME%"
placeholders:
enable-errors: false # false 时显示 default-message 而非报错
default-message: "N/A"
not-in-leaderboard-message: "未上榜"
playtime-leaderboard-blacklist: [] # 黑名单 UUID 列表
---- AFK 检测 ----
afk-detection-plugin: "essentialsx" # none/essentialsx/purpur/afkplus/jetsantiafkpro
afk-placeholder: "%essentials_afk%" # 当上方设为 none 时使用的 PAPI 占位符
ignore-afk-time: true # AFK 时间不计入总时长
---- 排行榜 ----
playtimetop:
leaderboard-format: "&e#%POSITION% &r%PREFIX%%PLAYER_NAME% &7- &b%PLAYTIME%"
page-size: 10
---- 隐身模式 ----
vanish-stealth-mode: true # v3.6.5+ 隐藏隐身玩家
---- 数据库(迁移后自动写入) ----
database:
type: "sqlite" # sqlite / mysql / mariadb / postgresql
MySQL / MariaDB / PostgreSQL 额外字段:
address: "127.0.0.1:3306"
database: "playtimemanager"
username: "root"
password: "yourpassword"
table-prefix: "ptm_"
---- 缓存 ----
cache:
enabled: true
reset-interval-minutes: 30 # 防内存泄漏的自动重置间隔
目标 YAML 示例(Goals/10h-reward.yml)
name: "10h-reward"
enabled: true
repeatable: true
requirements:
playtime: "10h"
permission: ""
placeholder-condition: ""
rewards:
messages:
- "&a恭喜!你已达到 10 小时在线时长!"
commands:
- "console:give %PLAYER_NAME% diamond 5"
permissions:
- "vip.basic"
sound: "ENTITY_PLAYER_LEVELUP"
连续登录 YAML 示例(JoinStreaks/7day-streak.yml)
name: "7day-streak"
enabled: true
required-joins: 7
cron-expression: "0 0 " # 每天凌晨检查
loop: true # 达到后循环回到第 1 天
reward-message: "&b连续登录 7 天!获得特殊称号!"
reward-commands:
"console:lp user %PLAYER_NAME% parent add streak7"
reward-icon:
material: "DIAMOND"
enchantment-glint: true
安装步骤
第一步:环境检查
确认服务端为 Paper 或 Purpur(Spigot 不支持)
确认 Java 版本 >= 17
确认 MC 版本在 1.19 – 26.2 范围内
第二步:下载与安装
从 Modrinth / Hangar / SpigotMC 下载 PlayTimeManager-3.6.5.jar
将 jar 文件放入服务端的 plugins/ 目录
如需 PAPI 占位符功能,同时安装 PlaceholderAPI 并运行 /papi ecloud download Player + /papi reload
如需 LuckPerms 联动,确保 LuckPerms 已安装并正常运行
第三步:首次启动
启动(或重启)服务器
插件会自动创建 plugins/PlayTimeManager/ 目录及默认配置文件
控制台应出现类似日志:
[PlayTimeManager] Plugin enabled successfully! Using SQLite for data storage.
第四步:基础配置
打开 config.yml,按需修改 prefix、datetime-format、afk-detection-plugin 等
如需切换数据库,修改 database 段落并运行 /playtimemigration start mysql
执行 /playtimereload 或重启服务器使配置生效
第五步:创建第一个目标
在游戏内执行 /playtimegoal 打开 GUI
点击 "Create New Goal" 按钮
设置名称、时长要求、奖励内容
保存后目标立即生效
升级迁移
从 v3.0.4 及以后版本升级:直接替换 jar,重启即可,插件自动备份并迁移配置
从 v3.0.4 之前版本升级:需先升级到 v3.1 过渡版,再升至最新版
升级前插件会自动备份整个 PlayTimeManager 文件夹,无需手动备份
搭配推荐
| 插件 | 搭配效果 |
| :--- | :--- |
| PlaceholderAPI | 解锁全部 PTM 占位符 + 嵌套占位符 + 第三方插件数据联动 |
| LuckPerms | 目标/连击达成后自动晋升权限组、显示前缀 |
| EssentialsX | 成熟的 AFK 检测数据源 |
| Vault | 经济系统联动,可用作奖励内容 |
| ajLeaderboards | 将 PTM 的 %PTM_playtime% 接入全服排行榜 |
| LiteBans | 被封禁玩家不计入在线时长统计 |
评论 (0)