[MD]
# GlobalMarket · 全球市场
> Minecraft 1.12.2 · Forge · 宝可梦 Reforged(Pixelmon)8.4.3
> 一个给玩家用的交易市场:物品和宝可梦都能挂出来卖,可以玩拍卖,还能给别的玩家寄东西。

---
## 目录
- [环境要求](#环境要求)
- [安装(服主看这里)](#安装服主看这里)
- [玩家上手](#玩家上手)
- [打开市场](#打开市场) · [找货:搜索与筛选](#找货搜索与筛选) · [卖货:两种卖法](#卖货两种卖法)
- [拍卖怎么玩](#拍卖怎么玩) · [给别人寄东西](#给别人寄东西) · [邮箱与历史](#邮箱与历史)
- [命令](#命令)
- [服主手册](#服主手册)
- [权限](#权限) · [配置一览](#配置一览configglobalmarketcfg) · [时长怎么写](#时长怎么写)
- [收哪种钱](#收哪种钱vault-还是-pokédollars) · [数据库](#数据库sqlite-默认--mysql)
- [商品悬浮说明自定义](#商品悬浮说明自定义) · [上架通知自定义](#上架通知自定义)
- [常见问题](#常见问题)
- [数据与备份](#数据与备份)
- [最近更新](#最近更新)
- [许可与致谢](#许可与致谢)
---
## 环境要求
| 项目 | 版本 |
| --- | --- |
| Minecraft | 1.12.2 |
| Forge | 14.23.5.2860(1.12.2 的较新版本均可) |
| 宝可梦 Reforged | **8.4.3**(必需,本模组就是按这个版本开发的) |
| Java | 8 |
> **客户端和服务端都要装本模组,而且两边要用同一个 jar。**
> 两边版本不一致时,客户端会提示"GlobalMarket 客户端版本不兼容,请更新模组"。
> 拿不准的时候,进游戏输入 `/globalmarket version` 就能看到两边的版本号。
---
## 安装(服主看这里)
1. 把 `GlobalMarket-1.1.0.jar` 放进**服务端和客户端**的 `mods/` 目录;
2. 确认 `mods/` 里已经有 **Pixelmon Reforged 1.12.2-8.4.3**(本模组依赖它);
3. 启动一次服务器,会自动生成:
- 配置文件:`config/GlobalMarket.cfg`
- 数据文件:`config/market.db`(默认就是一个文件,建表和升级全自动,不用管);
4. 进游戏按 **J** 打开市场(按键可以在"选项 → 控制"里改,分类在"游戏"里),
或者输入 `/globalmarket open`。
> 如果服务器启动时报"没有可用的 SQLite 驱动":把 `config/GlobalMarket.cfg` 里的
> `database.driver` 改成 `embedded`,并改用同版本发布的 `GlobalMarket-1.1.0-embedded.jar`
> (这个版本自带驱动)即可。
---
## 玩家上手
### 打开市场
按 **J**(或输入 `/globalmarket open`)就能打开市场:

- **30 个商品格子**(6 列 × 5 行),每张卡片只显示"图标 + 价格",
大金额会写成 `15M`、`1.2k` 这样的简写,鼠标指上去能看到完整金额;
- **搜索框**在左上角:输入关键词按回车立刻搜,停下手也会自动搜;
- **顶部按钮**:分类切换(全部 / 物品 / 宝可梦)、排序方式(最新 / 价格高低 / 等级高低)、
**筛选**(下一节细讲)、**售卖方式**(全部 / GTS 一口价 / 拍卖);
- **右侧查看器**:点选一只宝可梦后,这里会显示它的照片、等级、性格、特性、性别、
个体值、生命和六边形能力图,买之前先看个明白;
- **鼠标操作**:左键选中商品,右键可以快速买 1 个;
**自己的挂单点开是"下架",不能买自己的货**;
- **右下角**显示你还能上架多少件("剩余可上架数量");
- **底部一排按钮**:浏览 / 我的在售 / 上架 / 历史 / 邮箱 / 寄送,后面每个功能都有图。
### 找货:搜索与筛选
点顶部的「筛选」按钮打开筛选面板:

- 可以按 **闪光、性别、体型、等级区间、价格区间、个体值区间、特性** 来筛,
每一项都能设上下限,点「清除」一键恢复不限;
- **性格不用打字**:25 种性格直接铺在面板里,点一下就选中(再点一下"不限"或当前格取消);
- **特性**因为种类太多,保留了输入框,想筛什么特性打名字进去就行;
- 面板里那行"价格"筛的是**所有商品**,其余项目只对宝可梦生效;
- 所有筛选都在服务器那边完成,不用担心列表刷不出来。
### 卖货:两种卖法
市场里有两种卖法:**GTS(一口价)** 和 **拍卖**。这是两套独立的界面,各填各的,
不会搞混。四个上架入口用底部导航的「上架」进,然后在界面底部换页:
| 卖什么 | 入口 | 要填的 |
|---|---|---|
| 物品 · 一口价 | 上架 → 物品页 | 单价 + 数量 |
| 宝可梦 · 一口价 | 物品页 → 底部「上架宝可梦」 | 单价 |
| 物品 · 拍卖 | 物品页 → 底部「拍卖」 | 只填起拍价 |
| 宝可梦 · 拍卖 | 拍卖物品页 → 底部「上架宝可梦」 | 只填起拍价 |
每一屏底部都是三个按钮:**返回 / 换卖什么 / 换怎么卖**(直接跳到另一端)。
服务器如果关掉了拍卖,「拍卖」按钮就不会出现。
**① 一口价卖物品** —— 从背包格子里点选要卖的格子,填单价和数量,点「确认上架」:

**② 一口价卖宝可梦** —— 列表里直接点选(队伍里的排前面,其次 PC 里的),填单价确认:

**③ 拍卖** —— 和上面选货方式一样,但填的是**起拍价**(这一批货整批拍卖)。
拍卖显示多长时间是**服务器定好的**,玩家改不了,界面上只读给你看。
确认前会弹一个二次确认,写清楚卖什么、起拍价多少、拍多久:

不管哪种卖法,规则都一样:
- 挂出去的货由市场**代为保管**(从背包 / PC 里取走并原样保存),
下架或到期没卖掉都会**原样退回**,不会变质不会丢;
- 已经在市场上的宝可梦不会再出现在上架列表里;
- **队伍里的最后一只宝可梦不能上架**(PC 里的不受限);
- 一次性最多挂多少件由服务器设定(见右下角"剩余可上架数量");
- 上架成功后会收到一条聊天通知,**点一下就能直接打开市场界面**。
### 拍卖怎么玩
- **出价 = 先扣钱**:出价那一刻钱就从账户扣走、押在拍卖上;被别人超过会**立刻退回**,
所以到点开奖时不怕"中标的人临时没钱";
- **自己给自己加价只补差价**:比如你出过 1000,再出 1500 时只扣 500;
- **被超过会收到提示**:还在线的话,聊天栏会告诉你被谁超了;
- **到点自动开奖**(服务器每 10 秒扫一遍):
- 有人出价 → 货发给最高出价者(背包放不下就进邮箱),钱扣税后付给卖家;
- 没人出价 → 流拍,货退回卖家邮箱;
- **放心拍**:就算服务器中途崩了或重启,正在进行的拍卖也不会乱——钱不会丢,
重启后会自动接着把没做完的结算做完;
- **卖家注意**:有人出过价的拍卖**不能直接下架**(不然买家的钱就悬了),让它拍到结束即可;
- **界面**:拍卖卡片右下角有剩余倒计时,价格一栏显示当前最高价(青色);
选中后点底部「出价」打开出价界面,里面能看到当前价、出价次数、剩余时间、
最高出价者和最近 3 条出价记录;
- **拍多久是服务器定的**(默认 24 小时,服主可以改成 30 分钟速拍等,见配置里的
`auction.duration`),玩家没有任何地方能改它,命令里也不能填时长;
- 服务器还可以开**防狙击**:结束前最后一会儿有人出价,就自动顺延一小段时间,
给别人反应的机会(默认关闭,服主可开)。
### 给别人寄东西
想直接送东西给别的玩家?用底部导航的「寄送」:

- **寄物品**:填收件人名字 → 从背包格子里点一格 → 填数量 → 确认寄出。
**数量留空或填得比手里多,就按整组寄出**;
- **寄宝可梦**:点底部「寄宝可梦」切换过去,列表里选一只(队伍优先,其次 PC)→ 确认。
**队伍里的最后一只不能送出**(PC 里的不受限,不影响你打架);
- **对方不在线也能寄**:他上线后到市场邮箱里领就行(来源会写"好友寄送");
在线的话会立刻收到一句聊天提示;
- **只能寄给"服务器认识"的玩家**:也就是曾经进过这个服的玩家。名字打错会明确提示
找不到人,不会悄悄把东西寄丢;
- 和上架一样受**黑名单**限制,战斗中不能寄宝可梦;
- 每次寄送都有记录可查;万一寄的过程中出了岔子,东西会**原路退回**你的背包
(背包放不下就退到邮箱),绝不会凭空消失;
- 寄出前默认有二次确认(服务器可以选择关掉)。
### 邮箱与历史
**市场邮箱**:底部导航的「邮箱」。

- 这些情况收到的东西都会进邮箱:**买东西时背包满了**、**卖家不在线**、
**下架退回**、**挂单到期退回**、**系统补偿**、**好友寄送**;
- 按**图标卡片**展示,每页 5 条:左边是货物本身的图标(宝可梦显示照片,
钱显示金色 `$`),右边是名称、来源、金额和时间;
- 鼠标悬停看完整信息(包括物品描述和来源挂单号),**左键点这一行就领取**,
底部「全部领取」一键清空。
**交易历史**:底部导航的「历史」,分"我的购买 / 我的出售",同样是每页 5 条的卡片。
悬停能看到货物名称和描述、买家、卖家、数量、单价、实付金额、税金、交易状态和时间。
---
## 命令
界面上能做的,命令基本都能做;反过来有些操作只有命令有(比如把**手里拿着的**东西寄出去)。
`<>` 里是必填,`[]` 里是可选。
| 命令 | 说明 |
| --- | --- |
| `/globalmarket open [玩家]` | **打开市场界面**(和快捷键 J 一样;给别的玩家打开需要 OP) |
| `/globalmarket` 或 `/globalmarket listings` | 在聊天框里列出市场(不开界面) |
| `/globalmarket items` / `pokemon` | 只看物品 / 宝可梦 |
| `/globalmarket search <关键词>` | 搜索 |
| `/globalmarket selling` | 我的在售 |
| `/globalmarket sell <槽位0-35> <单价> [数量]` | 上架背包物品 |
| `/globalmarket sellpokemon party <0-5> <价格>` | 上架队伍宝可梦 |
| `/globalmarket sellpokemon pc <箱子> <格子> <价格>` | 上架 PC 宝可梦 |
| `/globalmarket auction <槽位> <起拍价> [数量]` | 以拍卖上架物品(起拍价是**整批**的价;拍多久由服务器统一设定,命令里不填) |
| `/globalmarket auctionpokemon party <0-5> <起拍价>` | 以拍卖上架队伍宝可梦(时长同上) |
| `/globalmarket auctionpokemon pc <箱子> <格子> <起拍价>` | 以拍卖上架 PC 宝可梦(时长同上) |
| `/globalmarket bid <编号> <出价>` | 对拍卖出价(钱立刻押上) |
| `/globalmarket buy <编号> [数量]` | 购买(物品可以只买一部分,按单价 × 数量算钱) |
| `/globalmarket cancel <编号>` | 下架自己的挂单 |
| `/globalmarket send <玩家> [数量]` | 把**主手拿着的物品**寄进对方的市场邮箱(不填数量 = 寄整组)。**对方不在线也能寄** |
| `/globalmarket sendpokemon <玩家> <队伍槽位0-5>` | 把队伍里的宝可梦**送给**对方。**对方不在线也能寄** |
| `/globalmarket history <bought\|sold> [页码]` | 交易历史(买 / 卖) |
| `/globalmarket mail` | 查看 / 领取邮箱 |
| `/globalmarket info <编号>` | 查看某条挂单详情 |
| `/globalmarket version` | 查看版本、经济与数据库状态(**排错第一步**) |
| `/globalmarket reload` | 重载配置(需要权限) |
| `/globalmarket admin ...` | 管理员专用:`remove`(强制下架)/ `release`(恢复暂停挂单)/ `inspect`(检查)/ `recover`(处理遗留交易)/ `audit`(查记录) |
---
## 服主手册
### 权限
| 权限 | 作用 |
| --- | --- |
| `globalmarket.admin` | 管理员子命令(`/globalmarket admin ...`) |
| `globalmarket.reload` | 重载配置 |
| `globalmarket.bypass.blacklist` | 不受物品 / 宝可梦黑名单限制(**上架与寄送都算**),适合管理员和活动账号 |
| `globalmarket.bypass.limit` | **完全不受上架数量限制** |
| 自定义(见下) | 按权限给不同玩家组分配上架额度 |
权限从哪来:**混合端(CatServer 等)读 Bukkit 权限**(LuckPerms、PermissionsEx 等都生效),
**纯 Forge 端读 Forge 权限**(默认按 OP 等级,装了权限模组就由它接管)。
#### 按权限分配上架额度(`limits.permission-tiers`)
默认所有玩家共用 `limits.max-active-listings` 这个"同时在售总数"上限。
想给 VIP、MVP 更高的额度,就在 `permission-tiers` 里写"权限节点 = 最大在售数":
```cfg
limits {
I:daily-listing-limit=0 # 已废弃,仅为兼容旧配置保留,不用管
I:max-active-listings=100
# 格式:权限节点=最大在售数;0 = 不限制
S:permission-tiers <
globalmarket.limit.vip=100
globalmarket.limit.mvp=300
globalmarket.limit.staff=0
>
}
```
- 上例含义:有 `globalmarket.limit.vip` 的玩家最多同时在售 100 件,MVP 是 300 件,
有 `globalmarket.limit.staff` 的**完全不限**;
- 一个玩家同时命中多个档位时,**取最宽的那一档**(只会放宽,不会低于 `max-active-listings`);
- 档位就是普通权限节点:给玩家加权限就行,不用改配置也不用敲命令
(LuckPerms 示例:`/lp user <玩家> permission set globalmarket.limit.vip true`);
- 想换权限节点的名字,改完 `/globalmarket reload` 即可;玩家重进服务器
(或重新打开市场界面)后,右下角的"剩余可上架数量"就会跟着变。
### 配置一览(`config/GlobalMarket.cfg`)
改完配置执行 `/globalmarket reload` 就能生效,**不用重启**(个别项除外,下面会标注)。
| 分类 | 配置项 | 默认 | 干什么用的 |
| --- | --- | --- | --- |
| market | `enabled` | true | 市场总开关 |
| economy | `provider` | auto | 收哪种钱:`auto`(有 Vault 经济就用 Vault,否则用宝可梦的 PokéDollars)/ `vault` / `pixelmon`,详见下文 |
| tax | `enabled` / `rate` | true / 5.0 | 成交是否收税 / 税率(%) |
| limits | `daily-listing-limit` | 0 | 已废弃,不起作用了,保留只为兼容旧配置 |
| limits | `max-active-listings` | 100 | 每人**同时在售**的总数量上限(0 = 不限制) |
| limits | `permission-tiers` | 空 | 按权限给不同玩家组更高的额度(写法见上一节) |
| price | `minimum` / `maximum` | 1 / 999999999999 | 允许的定价范围 |
| listing | `allow-item` / `allow-pokemon` | true / true | 允不允许上架物品 / 宝可梦 |
| listing | `expire` | `0` | 挂单挂多久没卖掉就自动下架退回,**`0` = 永不过期**。写法见「时长怎么写」 |
| listing | `expire-check-seconds` | 15 | 服务器每隔多少秒巡查一次过期(最小 10)。商品一到期就会从市场列表里消失,这里只影响"退货运进邮箱"的快慢 |
| listing | `stale-reservation-minutes` | 10 | 一笔买单如果中途出意外(比如保存瞬间断电),超过这个分钟数就会在日志里**大声报警**提醒你介入。模组不会自动去动玩家的货和钱(防止被人钻空子),需要管理员用 `/globalmarket admin` 处理 |
| auction | `enabled` | true | 拍卖行总开关。关掉后不能再出价,**已经在拍中的**到点按流拍处理、货退卖家 |
| auction | `duration` | `24h` | 每场拍卖拍多久(玩家不可选)。范围 1 分钟 ~ 7 天,写 `30m` 就是 30 分钟速拍。写法见「时长怎么写」 |
| auction | `min-increment` / `min-increment-percent` | 1 / 0 | 每次出价最少加多少:固定金额和"当前价的百分之几"**两个里取大的**(百分比填 0 = 关掉那一算法) |
| auction | `anti-snipe-enabled` | false | 防狙击开关:结束前有人出价就把结束时间往后顺延 |
| auction | `anti-snipe-window-seconds` / `anti-snipe-extend-seconds` | 30 / 30 | 结束前多少秒内出价算"最后一刻" / 每次顺延多少秒 |
| notify | `listing-created` | true | 玩家上架成功后,要不要发一条**可以点击**的聊天通知 |
| notify | `listing-created-message` | 空 | 通知正文,留空 = 内置文案(自动跟随玩家语言) |
| notify | `listing-created-hint` | 空 | 通知末尾那截可点击的文字,留空 = 内置文案 |
| notify | `listing-created-hover` | 空 | 鼠标悬停在通知上显示的说明,留空 = 内置文案 |
| notify | `listing-created-command` | /globalmarket open | 点击通知后执行什么命令;清空 = 通知不可点击 |
| network | `action-cooldown-millis` | 300 | 同一玩家两次市场操作(上架 / 购买 / 下架 / 领取)之间最少隔多少毫秒,0 = 不限。**看行情和操作分开计时**:刚上架完马上刷新列表不会被当成"操作太频繁" |
| network | `heavy-read-cooldown-millis` | 1000 | 「列出我的宝可梦」这类重活之间最少隔多少毫秒——这个操作要给每只宝可梦生成照片,设太短会卡服务器 |
| delivery | `enabled` | true | 邮箱总开关 |
| general | `timezone` | Asia/Shanghai | 显示时间用的时区 |
| database | `type` | sqlite | 数据库类型:`sqlite`(本地单文件,默认)/ `mysql`,详见下文 |
| database | `mysql-host` / `mysql-port` | 127.0.0.1 / 3306 | MySQL 地址和端口 |
| database | `mysql-database` | globalmarket | 库名(不存在会自动创建) |
| database | `mysql-username` / `mysql-password` | root / 123456 | MySQL 账号密码 |
| database | `mysql-create-database` | true | 库不存在时自动建库 |
| database | `driver` | server | 仅 SQLite 用:`server`(用服务端自带的驱动)/ `embedded`(用模组自带的驱动) |
| compat | `require-supported-pixelmon-version` | true | 检测到 Pixelmon 版本不匹配时,是否自动关闭市场(防止不兼容出乱子) |
| blacklist | `items` / `pokemon` | 空 | 禁止上架的物品 / 宝可梦名单:物品写 `modid:name`,宝可梦写 `Species` 或 `Species:Form` |
| tooltip | `item-lines` / `pokemon-lines` | 空 | 商品悬浮说明模板,每行一条;留空 = 内置默认,详见下文 |
另外三件事:
- `expire` 从 `0` 改成非 0 后,**之前挂着的"永不过期"挂单也会按新设置开始算到期**;
- 升级模组后,配置里已经废弃的选项会被自动清理,日志里会列出删了哪些;
- 只有**切换数据库类型**需要重启服务器,其它都能热重载。
#### 时长怎么写
`listing.expire`(挂单挂多久)和 `auction.duration`(拍卖拍多久)用同一套写法,**支持分钟**:
| 写法 | 意思 |
|---|---|
| `30m` | 30 分钟 |
| `2h` | 2 小时 |
| `1h30m` | 1 小时 30 分 |
| `1d` | 1 天 |
| `90` | **纯数字按分钟算**,即 90 分钟 |
| `0` | 关闭(对 `expire` 来说 = 永不过期) |
- 大小写和空格随意(`1H 30M` 也行),可以自由组合(`1d2h30m`);
- **不支持小数**:想写 1.5 小时,请写成 `90m`;
- **写错了服务器也不会起不来**:日志里提示一条警告,然后退回默认值
(`expire` → `0`,`auction.duration` → `24h`);
- 范围:挂单过期最长 10 年,拍卖时长 1 分钟 ~ 7 天;写得太大就自动卡在上限;
- 玩家看到的时长文案会自动挑合适的单位("2 小时" / "30 分钟" / "1 小时 30 分"),
中文客户端看中文、英文客户端看英文。
> **从旧版本升级**:原来按小时填的 `expire-hours` / `duration-hours`(比如 `6`)
> 会在**服务器启动时**自动换算成新写法(`6h`)写回配置,设置的值不会丢,
> 旧键随后被自动清理(日志里会列出)。
>
> 注意换算只在**启动**时做一次:`/globalmarket reload` 不会重新换算。
> 所以**升级后重启一次服务端**即可;也不要手动把旧键名写回配置再热重载
> (新键已经存在,会继续以新键为准)。
### 收哪种钱:Vault 还是 PokéDollars
默认 `economy.provider=auto`,模组自己挑:
- **混合服务端(CatServer / Mohist 等)装了 Vault + 经济插件**(EssentialsX、CMI 等)
→ 自动用 **Vault**:玩家余额、扣款、收款全走那个插件,货币名也用它(比如 `Coins`);
- **纯 Forge 服务端**(没有 Bukkit 那套)→ 自动用宝可梦自带的 **PokéDollars**,什么都不用配;
- 想指定某一种,就把 `provider` 写成 `vault` 或 `pixelmon`。
强制 `vault` 但服务器上没挂上时,会自动退回 PokéDollars 并打一条警告,
**服务器照常启动,不会崩**;
- 混合端里 Bukkit 插件比 Forge 模组加载得晚,所以市场会在服务器完全启动后、
以及每次要用钱之前自动去挂钩——启动日志里那几行 "Vault is installed but ..." 是正常现象,
插件加载完就自动用上了;
- 排查时先看 `/globalmarket version` 输出里的 `economy:` 一行,它显示当前实际用的是哪种。
### 数据库:SQLite(默认)/ MySQL
默认用 SQLite,就是一个文件(`config/market.db`),零配置。
**多台服务器想共用同一个市场**,或者想集中备份时,改成 MySQL:
把 `database.type` 改成 `mysql`,同段的 `mysql-*` 就是连接参数
(默认 `127.0.0.1:3306` / `root` / `123456` / 库名 `globalmarket`)。
- 库不存在会自动建;已存在的直接用;
- 需要 **MySQL 5.7.6+ 或 MariaDB 10.2+**;
- 需要服务器上有 MySQL 驱动:混合端(CatServer / Spigot)一般自带;
纯 Forge 端把 `mysql-connector-java-x.y.z.jar` 放进 `config/globalmarket/jdbc/` 即可;
两处都没有的话,启动日志会直接告诉你;
- **改 `type` 要重启服务器**;`/globalmarket version` 会显示当前用的数据库和位置;
- 切换数据库**不会自动搬旧数据**,但两边表结构一致,用任何数据库工具都能导出导入。
### 商品悬浮说明自定义
市场里鼠标指到商品上显示的那段文字,**服务器改一次、所有玩家生效**(按玩家自己的语言显示):
```cfg
tooltip {
S:item-lines <
&f{name}
&7{icon_info}
&a{lang:globalmarket.gui.row.price} {currency}{price}
&7{tax_line}
&7{lang:globalmarket.gui.row.seller} {seller}
&8{left_line}
-
&8{lang:globalmarket.gui.hint.buyFast}
>
S:pokemon-lines <
&f{name} {shiny}
&7{lang:globalmarket.gui.row.level} {level} &7{lang:globalmarket.gui.row.nature} {nature}
&8{lang:globalmarket.gui.row.iv} {iv_hp}/{iv_atk}/{iv_def}/{iv_spa}/{iv_spd}/{iv_spe} &8{lang:globalmarket.gui.row.iv} {iv_total}
&8{lang:globalmarket.gui.row.held} {held} {pokerus}
&a{lang:globalmarket.gui.row.price} {currency}{price}
&8{left_line}
>
}
```
规则:
- 每行一条;单独写一行 `-`(减号)就是一条分隔线;**留空 = 用内置默认**;
- **配了模板就完全按模板显示**:模组不再自动追加任何内容——名称、税收、
"右键快速购买"提示等都得靠占位符自己排(上面的示例就是完整写法);
- 颜色代码:`&7` 灰、`&a` 绿、`&c` 红、`&l` 加粗(直接写 `§` 也行);
- `{lang:词条键}` 会自动换成**玩家客户端语言**的文字,比如
`{lang:globalmarket.gui.row.price}` 中文显示"价格"、英文显示"Price";
- 开了税之后,想显示"税收 ¥50(税率 5%)"这一行,用 `{tax_line}` 占位符;
- 显示出来是空的行会自动省略;写错的占位符会原样露出来,方便你发现拼错了。
**物品和宝可梦通用的占位符:**
| 占位符 | 显示什么 |
| --- | --- |
| `{id}` | 商品编号 |
| `{type}` | 类别(物品 / 宝可梦) |
| `{name}` | 名称(物品名或宝可梦名) |
| `{price}` / `{price_compact}` | 单价(完整 / `1.2k` 简写) |
| `{currency}` | 货币符号(跟经济插件走) |
| `{total}` | 把剩下的全买下来的总价 |
| `{quantity}` / `{remaining}` / `{sold}` | 总数量 / 剩余 / 已售出 |
| `{seller}` | 卖家名 |
| `{listed}` / `{expires}` | 上架时间 / 过期时间 |
| `{left}` / `{left_line}` | 剩余时间 / 整行"剩余 xx"(永不过期时整行消失) |
| `{item_id}` | 物品注册名(`modid:name`,宝可梦挂单为空) |
| `{icon_info}` | 物品自带的说明(附魔、lore、耐久,宝可梦照片资料等,可能多行)。模板里**单独占一行**,渲染时按内容展开;没内容时整行自动省略;模板里不写它就不显示(此时也不解析图标) |
| `{tax}` / `{tax_total}` | 卖 1 个要交的税 / 剩下的全卖掉的税(没开税时为空) |
| `{tax_rate}` | 税率文字(`5%`、`2.5%`;没开税时为空) |
| `{tax_line}` | 整行"税收 ¥50(税率 5%)",没开税时整行消失 |
**宝可梦专用**(物品挂单上这些全是空的,所以可以共用一份模板):
| 占位符 | 显示什么 |
| --- | --- |
| `{species}` / `{dex}` | 种类名 / 全国图鉴编号 |
| `{form}` / `{form_name}` | 形态编号 / 形态名 |
| `{nickname}` | 昵称(没有就是空) |
| `{level}` | 等级 |
| `{nature}` / `{ability}` | 性格 / 特性 |
| `{gender}` | 性别(♂ / ♀ / 无性别) |
| `{growth}` | 体型(迷你 → 巨大 等) |
| `{shiny}` | 闪光标记(`§e★`,非闪光为空) |
| `{held}` | 携带物品名 |
| `{ball}` | 球种 |
| `{ot}` | 初训家 |
| `{iv_total}` / `{ev_total}` | 个体值总和(/186)/ 努力值总和(/510) |
| `{hp}` / `{max_hp}` | 当前生命 / 最大生命 |
| `{moves}` | 招式(`/` 分隔,最多 4 个) |
| `{pokerus}` / `{egg}` | 病毒 / 蛋:有 = 绿色 ✓,没有 = 空串(整行自动省略) |
| `{iv_hp}` `{iv_atk}` `{iv_def}` `{iv_spa}` `{iv_spd}` `{iv_spe}` | 六项个体值(生命 / 攻击 / 防御 / 特攻 / 特防 / 速度) |
| `{ev_hp}` `{ev_atk}` `{ev_def}` `{ev_spa}` `{ev_spd}` `{ev_spe}` | 六项努力值 |
| `{stat_hp}` `{stat_atk}` `{stat_def}` `{stat_spa}` `{stat_spd}` `{stat_spe}` | 实时能力值(算上性格、努力加成后的当前数值) |
**宝可梦名字会自动翻译**:`{name}`、`{species}`、`{form_name}`、`{nature}`、`{ability}`、
`{ball}`、`{moves}`、`{growth}` 这些会优先显示**玩家客户端语言**的名字
(皮卡丘 / 固执 / 静电 / 十万伏特 / 精灵球……),该语言没有的词条退回英文名;
玩家自己起的昵称永远最优先。
### 上架通知自定义
玩家上架成功后会收到一条聊天消息,**点一下直接打开市场界面**(默认执行 `/globalmarket open`):
```cfg
notify {
B:listing-created=true
S:listing-created-message= # 正文,留空 = 内置文案(跟随玩家语言)
S:listing-created-hint= # 末尾可点击的文字,留空 = 内置文案(默认「[点击打开市场]」)
S:listing-created-hover= # 鼠标悬停说明,留空 = 内置文案
S:listing-created-command=/globalmarket open # 点击后执行的命令;清空 = 不可点击
}
```
模板写法和悬浮说明**完全一样**(`&` 颜色代码、`{占位符}`、`{lang:词条键}`),可用占位符:
| 占位符 | 显示什么 |
| --- | --- |
| `{name}` | 货物名称 |
| `{quantity}` | 上架数量(宝可梦固定为 1) |
| `{price}` / `{price_compact}` | 单价(完整 / `1.2k` 简写) |
| `{total}` / `{total_compact}` | 总价(单价 × 数量) |
| `{currency}` | 货币符号 |
| `{id}` | 商品编号 |
| `{seller}` | 卖家名 |
| `{type}` | 类别(物品 / 宝可梦) |
例:`S:listing-created-message=&a已上架 &f{name}&a x{quantity},单价 &6{currency}{price}&a(商品 #{id})`
留空时的内置文案自带中英文,玩家可以点、也可以无视,不占聊天框多少地方。
---
## 常见问题
**客户端提示"GlobalMarket 客户端版本不兼容,请更新模组"?**
客户端和服务端的 jar 版本不一致,两边换成同一个 jar;用 `/globalmarket version` 看双方版本。
**界面文字显示成一串英文 key(比如 `globalmarket.gui.title`)?**
确认客户端语言设置是中文;必要时按 F3+T 重载资源。
**挂单过期了,邮箱里却没有?**
先看 `listing.expire` 是不是 `0`(`0` = 永不过期,永远不会退)。过期退回一律进邮箱,
卖家在线时还会收到一句聊天提示;过期退回每轮最多处理 5 条,积压多时会分几轮清完。
**为什么买不了自己的挂单?**
有意设计的。自己的货用"下架"拿回来就行。
**宝可梦上架失败?**
常见原因:这只宝可梦已经在市场上、是队伍里的最后一只、在黑名单里、正在战斗、
价格超出 `price` 范围、达到在售数量上限。
**权限给了,但额度没变?**
混合端读 Bukkit 权限(LuckPerms 等),纯 Forge 端读 Forge 权限;
确认玩家在线、权限节点和配置里写的**一字不差**,然后 `/globalmarket reload`,
再让玩家重进服务器,或用 `/globalmarket version` 核对。
---
## 数据与备份
- 默认所有数据都在 `config/market.db` 这一个文件里,**备份它就等于备份整个市场**;
用 MySQL 时数据在对应的库里,按平时的数据库备份流程做即可;
- 模组升级时数据库结构自动升级,**不会丢数据**;
- 有异常挂单或遗留交易,管理员用 `/globalmarket admin audit` 查、`/globalmarket admin recover` 处理。
---
## 最近更新
最近一次更新改了什么(大白话版)见 **[WHATSNEW.md](WHATSNEW.md)**;
完整开发记录见 [CHANGELOG.md](CHANGELOG.md)。
---
## 许可与致谢
- 本模组以 MIT 许可发布;
- **不含**任何 Pixelmon 的资源或代码,运行需要玩家自行安装 Pixelmon Reforged;
请遵守 Pixelmon 的授权条款,不要随包分发 Pixelmon。
[/MD]