跳到主要内容

跨服设置

星月市集跨服只需要一个 MySQL(或 MariaDB)数据库,不需要在代理端(BungeeCord / Velocity)安装任何东西,也不需要 Redis。 所有子服连同一个数据库后:

  • 在任何一个子服上架的商品,所有子服的市集都看得到、买得到;
  • 别的子服的上架、成交、出价,大约每秒同步一次;
  • 每一笔交易只会成交一次,两个子服同时抢也一样;
  • 买到的、卖出的东西都寄到玩家的星月邮箱,每一笔只寄一封,在哪个子服领都可以(星月邮箱也要共用数据库,见 下方);
  • 东西卖出、出价被超过时,不论卖家在哪个子服都会收到通知;
  • 各子服的经济插件不需要互通。

设置步骤​

  1. 建一个 MySQL 数据库,例如 starauction(字符集 utf8mb4),准备好每个子服都连得到的账号。
  2. 每个子服的 plugins/StarAuction/config.yml 填同样的数据库,server-id 填不同的名字:
database:
type: mysql
host: 192.168.1.10
port: 3306
database: starauction
username: starauction
password: '你的密码'
table-prefix: 'sa_' # 所有子服要一样
pool-size: 8

sync:
enabled: auto
server-id: 'lobby' # 每个子服不同:lobby、survival、skyblock…
interval-ms: 1000
  1. 重启每个子服(数据库与跨服设定 /sa reload 不会生效)。控制台会显示:
[StarAuction] 数据库已连接:MySQL 192.168.1.10:3306/starauction
[StarAuction] 跨服已开启(子服 ID:lobby,每 1000 毫秒同步一次其他子服的上架、成交与出价)
  1. 在每个子服输入 /sa version,确认都显示 MySQL 和正确的子服 ID。
  2. 星月邮箱也照同样的方式设成跨服(每个子服连同一个 MySQL、同样的 table-prefix),见下方 星月邮箱也要跨服。
server-id 一定要填

不填也能跨服,但每次开服会自动生成一个随机名字(端口 + 随机字符),成交记录、/sa log、/sa trades 里就看不出是哪个子服了。

表格前缀要一样

table-prefix 不同的子服之间互相看不到商品(它们用的是不同的表格)。同一个数据库里想放好几套互不相通的市集(例如生存服一套、创造服一套)时,才需要故意设不同的前缀。

怎么同步​

每个子服在内存里保留一份所有上架中商品的副本,逛市集、搜索、排序都不查数据库,非常快。

  • 每一次上架、成交、出价、下架、到期,都会在数据库的事件表写一行。
  • 每个子服每隔 sync.interval-ms(默认 1000 毫秒)查一次「编号比上次大的事件」——只查一个有主键索引的表,每秒一次也几乎没有负担。
  • 查到有变动的商品就重新读那几件;查到「某位玩家有新东西要寄」,就帮忙把待寄清单寄出,那位玩家正在这个子服时也通知他。
  • 玩家开着的市集菜单 / 云界面画面会自动刷新。
  • 另外每 full-refresh-seconds(默认 300 秒)完整重新读取一次全部上架中的商品,作为保险。

调小 interval-ms 同步更快,但每个子服的查询次数也更多;一般 500 ~ 2000 毫秒都很合适。

每笔交易只成交一次​

每一次购买、出价、卖给收购单、下架都是一个数据库事务,第一步是一条带条件的更新: 「这件商品还在上架、还没到期、剩余数量够、价格(或出价次数)和玩家看到的一样」。只有条件完全符合时才成交,然后在同一个事务里把要给双方的物品与货币写进待寄清单、写入成交记录。

  • 玩家 A 在 lobby、玩家 B 在 survival,同时买同一件只剩 64 个的商品、各买 64 个:只有一个成交;另一个提示「这件商品已经卖完、结束或被下架了」,他已经付的钱马上退回。
  • 两个子服同时有人出价:只有先到的那个成功,另一个提示价格变动、退回出价。
  • 卖家在 lobby 改价的同时买家在 survival 按确认:价格对不上,不成交,买家要看清新价格重新确认。

星月邮箱也要跨服​

1.1.0 起,市集给玩家的东西都寄到 星月邮箱。邮件存在星月邮箱自己的数据库里,所以跨服时:

星月邮箱的设置结果
每个子服的星月邮箱都连同一个 MySQL(同样的 table-prefix)✅ 推荐。不论哪个子服寄出,玩家在任何子服都能领;每封邮件只能领一次,见星月邮箱的 跨服设置
每个子服的星月邮箱各自用 SQLite❌ 不要这样用。一笔东西由哪个子服先寄就存进那个子服的邮箱,玩家在别的子服看不到;而且「同一笔只存一次」的保证只在同一个星月邮箱数据库里有效

星月邮箱的数据库可以和星月市集放在同一个 MySQL(用不同的数据库名称或表格前缀),也可以分开。

每一笔只寄一次​

待寄清单里的每一笔,任何一个子服都可能去寄:

  • 寄之前先「租下」那一笔一分钟(数据库条件更新,同一时间只有一个子服拿得到);
  • 邮件带着唯一编号 starauction:<安装编号>:<这一笔的编号>,星月邮箱对同一个编号只存一封;
  • 星月邮箱回传邮件编号后才标记为已寄出。寄到一半当机、等待回应超时,一分钟后由任何一个子服重寄,玩家也只会收到一封。

「安装编号」是这套市集数据库第一次寄信时随机产生、存在数据库里的,所有子服共用;所以两套互不相通的市集(不同的 table-prefix)共用一个星月邮箱时,编号也不会撞在一起。

领取与通知​

领取由星月邮箱负责:每封邮件只能领一次,就算两个子服同时点领取也一样,见星月邮箱的 每封信只领一次。

通知也一样:每一条「东西卖出了」「出价被超过」只会在玩家所在的那一个子服显示一次。

各子服的经济不同步也没关系​

星月市集从不远程操作别的子服的经济:

  • 买家付款:在买家所在的子服、从买家的帐户扣除。
  • 卖家收入、退款:寄到卖家的星月邮箱,卖家在哪个子服领取,就存进他在那个子服的帐户。

所以:

  • 每个子服用各自的经济插件、各自的余额,也不会出现多给或少给。
  • 不需要经济插件支持「给离线玩家加钱」。
  • 如果你的经济本来就是跨服同步的(例如共用一个经济数据库),也照样正常:钱只在玩家在线的那个子服进出一次。

每个子服都要装好对应的插件(Vault 经济插件、PlayerPoints),否则那个子服不能用那种货币交易;邮件里的金币 / 点券在没装的子服也领不了,会留在邮箱里等玩家到能领的子服再领。

到期结算​

每个子服每 10 秒检查一次到期的商品。好几个子服同时检查到同一件时,数据库的状态检查保证只有一个子服结算: 一口价剩下的物品退回、拍卖交给最高出价者(或流拍退回)、收购单退回没用完的预付款。所有子服都关着的期间到期的商品,在第一个开服的子服结算。

其他跨服行为​

项目跨服时
上架数量上限所有子服合计(从数据库数)
上架冷却每个子服各自计算
/sa view <玩家>、/sa remove <玩家>、/sa log <玩家>只要对方在任何一个连同一数据库的子服上线过,就找得到
成交记录、交易记录、/sa log、/sa trades所有子服的记录都在一起,每条显示子服 ID
成交均价所有子服的成交一起算
新商品全服公告只在上架的那个子服公告
config.yml 的规则(价格、黑名单、权限组…)每个子服各自一份,按执行操作的那个子服的设定检查。建议所有子服用同一份设定
messages.yml、categories.yml、菜单每个子服各自一份,需要的话自己复制到每个子服

子服的 Minecraft 版本要一致​

商品物品以 Paper 的完整物品数据保存。新版本服务器存的物品,旧版本服务器读不懂(旧版本存的物品,新版本可以读)。

如果子服版本不同,例如大厅是 1.21.11、生存服是 1.21.4:在大厅上架的商品,在生存服的市集会显示成屏障「物品资料无法读取」,不能卖给它的收购单; 买到的物品寄到星月邮箱后,在生存服领取时星月邮箱会提示附件数据无法读取,邮件留在邮箱里——东西不会丢,到 1.21.11(或更新版本)的子服就能领。

建议所有共用数据库的子服使用相同的 Minecraft 版本。

从单服换成跨服​

从 SQLite 换成 MySQL 不会自动搬移原本 data.db 里的商品与还没寄出的东西(星月邮箱也一样不会搬移邮件)。换之前请让玩家先下架商品、领完星月邮箱里的附件,或在旧服务器上保留一段时间。