Metro 月票 / 学生票插件,购买后 30 天内乘车不花钱
| 能力 | 说明 |
|---|---|
| 免费乘车 | 持票期间乘车费用由插件全额返还,覆盖月票与学生票 |
| 不改本体 | 纯附属插件实现,Metro 本体零修改、零补丁 |
| 续费叠加 | 未过期时再次购买从当前到期时间顺延 |
| 运营工具 | 发放 / 移除 / 查询 / 统计审计(票款 vs 报销) |
| 全可配置 | 价格、有效期、消息文本、风控上限均在 config.yml |
Metro 1.x 没有任何票价拦截点:扣费在"玩家上车成功之后"由 TicketService 直接执行,
附属插件既拿不到扣费事件、也无法豁免金额。MetroPass 采用如下纯插件方案(不改本体):
| 阶段 | 时机 | 动作 |
|---|---|---|
| 垫付 | 右键车站铁轨 / 在乘车 GUI 点击线路(均早于 Metro 的余额检查) | 把玩家余额补足到"该站最低票价估算 + 缓冲",避免余额不足被拒载 |
| 报销 | 扣费完成后(上车后 1 tick / 到站 DOCKED / 下车后 2 tick / 离线) | 比对观察窗口的前后余额差量,把 Metro 扣走的车费原额退还 |
| 回收 | 上车结算完成后 / 会话结束(下车、超时、离线) | 收回垫付的临时资金,只保留玩家自有余额 |
由于 Metro 的"已扣费 $X"提示无法拦截,玩家会先看到扣费消息,紧接着收到 "月票已覆盖本次车费,已原路退还"的提示(可在 config 中关闭提示)。
- 购票:
withdraw(钱从玩家账户扣除,等价于系统回收); - 报销:
deposit(按实际乘坐金额发放)。
建议月票定价覆盖预期乘车成本(/metropass admin stats 可查看"累计票款 vs 累计报销"用于调价)。
所有金额操作均有单次上限保护(fare-guard.max-refund-per-segment / max-reserve),
异常情况会写入控制台告警。
- 服务端:Paper / Spigot 1.18.2+;已安装 Metro 1.1.9(其他版本未经核对)与 Vault + 经济插件。
- 将
metro-pass-2.0.0.jar放入plugins/。 - 重启服务器。控制台应出现:
FareGuard 已启用:持票玩家乘车产生的车费将通过垫付-报销方式全额返还。
若未出现该行,请检查日志中的
FareGuard警告(通常是 Metro 版本不符或缺少 Vault 经济)。
| 命令 | 说明 | 权限 |
|---|---|---|
/metropass buy monthly |
购买/续费月票(未过期顺延 30 天) | metropass.use(默认所有人) |
/metropass buy student |
购买/续费学生票 | 同上 |
/metropass status |
查看剩余时间 | 同上 |
/metropass admin give <玩家> <monthly|student> [天数] |
发放 | metropass.admin(默认 OP) |
/metropass admin remove <玩家> [monthly|student] |
移除 | 同上 |
/metropass admin info <玩家> |
查询 | 同上 |
/metropass admin stats |
售票/报销统计 | 同上 |
/metropass admin reload |
重载配置 | 同上 |
别名:/mpass。
prices:
monthly: 100.0 # 月票价格
student: 50.0 # 学生票价格
ticket-names:
monthly: "月票"
student: "学生票"
time-units:
day: "天"
hour: "小时"
minute: "分钟"
second: "秒"
duration-days: 30 # 每张票的有效期(天)
fare-guard:
enabled: true # 免费乘车总开关(false = 只记录票,乘车照常付费)
max-refund-per-segment: 10000.0 # 单次报销上限(安全阀)
max-reserve: 10000.0 # 单次垫付上限(安全阀)
reserve-buffer: 1.0 # 垫付缓冲
session-timeout-seconds: 15 # 垫付会话超时(未乘车则回收)
notify-refund: true # 报销到账提示
debug: false # 排查日志ticket-names 设置玩家看到的月票/学生票名称;time-units 设置剩余时间的单位,默认使用中文,可按需修改为其他语言。命令参数仍使用 monthly 和 student,无需修改。
数据保存在 plugins/MetroPass/passes.yml(旧版写在 config.yml 里的记录会自动迁移)。
- 聊天里先显示扣费、又退款? 这是设计使然(见"工作原理")。Metro 的提示无法拦截/改写。
- 支持 Folia 吗? 暂不支持(未声明
folia-supported)。 - 升级 Metro 怎么办? FareGuard 依赖 1.1.9 的时序。升级后建议先在测试服验证一遍:
正常情况是"扣费后立即退款";若 Metro 大改流程导致未能退款,最坏结果为乘客正常付费
(不存在多扣/重复扣款),可在 config 中关闭
fare-guard过渡。 - 和 metro-altroutes 冲突吗? 不冲突:altroutes 负责"检修线路拦车",MetroPass 只在扣费前后做资金对冲。
需要 JDK 21+(验证于 JDK 25)与 Maven 3.9+:
mvn package
libs/metro-1.1.9.jar 为 Metro 官方 jar(上游未发布到公共仓库,做法与 metro-altroutes 一致),
升级 Metro 时替换该文件并同步修改 pom.xml 中的版本号。
仓库内置两套工作流,推送后自动生效:
- CI(
.github/workflows/ci.yml):push / PR 时自动编译并运行单元测试, 构建产物metro-pass-*.jar可在 Actions 页面的 Artifacts 中下载; - Release(
.github/workflows/release.yml):推送符合vX.Y.Z格式的标签(如v2.0.1)后, 自动编译、运行测试、附上版本说明,并在 Releases 创建 GitHub Release,附带插件 jar。也可在 Actions 页面手动指定已有标签发布。
本地打标签发布:
git tag -a v2.0.1 -m "MetroPass v2.0.1"
git push origin v2.0.1
- 新增可配置的月票、学生票名称,以及剩余时间单位;
- 默认显示中文,可通过
config.yml修改为其他语言; - 新增推送版本标签后自动构建并发布 GitHub Release,附带插件 JAR。
- 重写"免费乘车"为不修改 Metro 本体的垫付-报销机制(原 1.0.0 依赖不存在的
MetroFareEvent,无法编译与运行); - 新增续费叠加、管理员命令(give/remove/info/stats/reload)、统计审计;
- 票据数据迁移至独立
passes.yml,过期自动清理; - 全部消息可配置,默认中文。