跳到主要内容

⚙️ 关键配置说明

plugins/SparrowSync/config.yml 中有些选项会影响跨服数据的保留、在线回滚和保存时机。本页说明这些选项的用途,以及修改前需要了解的取舍。

以下代码块均为主配置中的相关片段,请在已有配置中找到对应位置修改。


📦 未知数据的保留与丢弃​

config.yml · 未知数据
synchronization:
# 本服无法识别的数据类型中,哪些需要丢弃;未列出的会保留。
# 修改后重启生效。
discard-unknown-data:
- sparrow_sync:attributes
- sparrow_sync:enchantment_seed
- sparrow_sync:experience
- sparrow_sync:flight_status
- sparrow_sync:game_mode
- sparrow_sync:health
- sparrow_sync:hunger
- sparrow_sync:location

各服需要同步的数据不一定相同。某台服务器关闭了一类数据的同步,或没有安装提供这类数据的插件时,Sparrow Sync 会把快照中对应的内容视为未知数据。默认情况下,这些数据会被保留,随之后的快照继续保存,等玩家回到能够识别它的服务器时再使用。

丢弃列表只处理未知类型

列入 discard-unknown-data 的类型会在本服无法识别时被丢弃。如果本服仍然启用了该类型的同步,它依旧会正常加载和保存,加入此列表不会禁用同步。

保留还是丢弃,取决于这份数据离开本服后是否还需要继续使用。暂时用不到、回到原服还要用的数据应该保留;由各服独立管理,或已经交给其他插件接管的数据,则需要考虑丢弃,避免旧记录继续随玩家流转。下面用游戏模式和货币说明这两种选择。

游戏模式为什么通常需要丢弃​

sparrow_sync:game_mode 已在默认丢弃列表中。例如,生存服和大厅服各自管理玩家的游戏模式,大厅关闭了游戏模式同步。玩家进入大厅后,来自生存服的模式没有必要一直留在后续快照中;将它丢弃,可以避免这份旧记录经过其他服务器后又被带回。

如果需要各服共享游戏模式,应在对应服务器启用 synchronization.data-types.game-mode。丢弃列表只处理本服未注册的类型。

货币数据要看谁来管理​

游戏模式通常可以由各服独立决定,但货币余额往往需要跨服延续。即使本服暂时不用这份余额,玩家回到有经济系统的服务器时也可能仍然需要它。因此,sparrow_sync:vault 没有列入默认丢弃列表,需要根据货币由谁管理来决定。

场景如何处理
只是路过没有经济系统的服务器保留货币数据,让原有余额随快照继续传递。
货币已交给其他插件负责跨服同步关闭 Sparrow Sync 的 Vault 同步,并将 sparrow_sync:vault 加入丢弃列表,停止传递旧余额。

后一种情况下,新保存的快照不再继续携带旧的货币数据,避免以后重新启用时又加载到过时余额。已有历史快照不会因此被批量修改。


⚡ 在进服前加载数据​

config.yml · 进服前加载
synchronization:
# 提前加载玩家数据,减少进服时同步造成的卡顿,推荐开启。
# 出现登录异常或兼容问题时,可尝试关闭对应项。
native-async-apply:
# 玩家基础数据
player-data: true
# 成就进度
advancements: true
# 统计信息
statistics: true

这组选项默认开启。Sparrow Sync 会在玩家尚未完全进入服务器时接管原有的数据加载流程,提前准备快照,并将数据注入服务器的玩家数据加载过程,减少进入游戏后集中回填数据造成的卡顿。

其中,player-data 控制玩家基础数据,advancements 和 statistics 分别控制成就进度与统计信息。通常建议保持开启,遇到登录或插件兼容问题时再尝试关闭对应项。

Paper 1.21.7+ 的出生点事件兼容性

第三方插件如果通过旧的 PlayerSpawnLocationEvent 处理出生点,会使玩家对象提前创建。成就和统计信息可能因此退回进服途中的同步加载,减少该优化带来的收益。

并非所有修改出生点的方式都会触发这一情况。


❤️ 在线回滚为什么默认跳过血量​

config.yml · 在线回滚
synchronization:
# 在线恢复快照时跳过这些数据,不影响登录同步。
# 留空则恢复全部数据。
skip-online-restore-data:
- sparrow_sync:health
- sparrow_sync:location

这个列表只影响对在线玩家恢复快照,不影响登录时的数据同步。默认跳过 sparrow_sync:health 和 sparrow_sync:location,避免恢复背包等数据时,同时改变玩家的血量和位置。

在线回滚血量还涉及生死状态切换。Sparrow Sync 可以写入对应的血量状态,但不会为了恢复快照而主动触发死亡事件。死亡事件会让其他插件处理掉落物、死亡惩罚、墓碑等内容,而回滚过程中没有一个适用于所有插件的事件顺序。

事件顺序可能造成的问题
先触发死亡,再回滚其他插件处理了本应被回滚替换掉的物品。
先回滚,再触发死亡刚恢复的物品又被死亡处理取走或扣除,造成再次丢失。
建议保留 health

因此,不推荐在线回滚时恢复血量。除非已经确认服内相关插件的行为,否则请将 sparrow_sync:health 保留在跳过列表中。


🗺️ 开启地图处理前需要了解什么​

config.yml · 地图处理
synchronization:
map:
# 是否处理跨服地图,默认关闭,修改后重启生效。
# 开启会修改地图物品,卸载后无法保证完整还原。
enabled: false
# SYNC:同步地图内容;HIDE:阻止地图在其他服务器使用。
synchronization_mode: SYNC

地图处理默认关闭。Sparrow Sync 能处理经过自身保存和跨服加载流程的地图物品,但无法覆盖所有插件转移物品的方式。

地图物品通过一个数字编号,也就是地图 ID,找到对应的地图内容。原版通常从 0 开始分配这些编号,各服务器独立管理,因此两台服务器上的同一个 ID 可能对应完全不同的地图。

例如,全球市场、跨服交易行或插件背包可能直接将地图送到另一台服务器,绕过 Sparrow Sync 的保存与加载流程。地图原有的 ID 可能在目标服务器上指向另一张地图,导致身份被错误解释、内容被替换。仅开启地图同步无法保证这类流转安全。

先确认地图的跨服流转方式

开启前,请先确认服内有哪些方式可以跨服转移地图,尽量确保它们会经过 Sparrow Sync 的同步流程。无法保证时,建议继续保持关闭。

确认地图的流转方式后,还需要决定跨服时如何处理它:是让玩家在新服务器上继续查看原来的内容,还是只阻止外服地图被错误使用?Sparrow Sync 分别提供了 SYNC 和 HIDE 两种模式。

为了在目标服务器保存同步过来的地图,同时避开原版使用的非负编号,SYNC 会由插件另外分配小于 0 的地图 ID。这些负数 ID 是 Sparrow Sync 创建的本地编号,用来关联同步后的地图物品与地图数据文件。HIDE 不需要保存外服地图内容,因此也不需要分配这组编号。

模式同步地图内容分配负数 ID用途
SYNC是是跨服后继续查看地图。
HIDE否否阻止外服地图显示本服地图画。

SYNC:同步地图内容​

将 synchronization.map.enabled 设为 true,并使用 synchronization.map.synchronization_mode: SYNC,插件会同步地图内容,让玩家跨服后仍能查看地图。

同步时,插件会使用前面介绍的负数 ID,创建对应的地图数据文件,并让地图物品指向这些数据。这会大幅改变地图数据的处理方式。其他插件可能默认地图 ID 非负,或自行管理地图文件,因此无法保证与所有地图相关插件兼容。发现冲突时,请提交 Issue 或反馈给作者,以便补充兼容。

开启后,地图物品和数据会发生变化,卸载 Sparrow Sync 也无法保证完整还原。请在理解这些影响后再启用。

HIDE:阻止跨服使用地图​

如果不需要跨服查看地图内容,只希望阻止外服地图被误用,可以开启地图处理并将模式设为 HIDE。它会让地图在其他服务器上无法使用,无需像 SYNC 那样分配负数 ID 和保存地图内容。

这个模式用于避免 ID 冲突让一张外服地图意外显示本服的地图画,进而被玩家恶意带走或窃取。它同样依赖地图经过 Sparrow Sync 的处理,不能覆盖绕过插件的直接交易。


地图来源标识:世界重置后如何处理旧地图​

config.yml · 地图来源标识
synchronization:
map:
# 用服务器 ID 和地图所属主世界的 UUID 区分地图来源。
# 修改后重启生效。
map-owner-id: '${server-id}-${world-uuid}'

map-owner-id 用来判断地图是否属于当前服务器的世界。${server-id} 对应 server.yml 中的服务器 ID,${world-uuid} 对应地图所属主世界的 UUID。默认将两者组合起来,因此即使服务器 ID 不变,重置世界后只要 UUID 发生变化,新旧世界也会被视为不同的地图来源。

在 SYNC 模式下,这个选择决定了旧地图回到重置后的服务器时,是继续作为本地地图更新,还是保留为旧世界的地图。

反复重置的地牢世界:希望地图继续更新。 如果地牢每轮都会重置,世界 UUID 也不断变化,但你希望玩家手里的地图继续绘制当前这一轮地牢,可以去掉 ${world-uuid},只使用固定的服务器 ID:

config.yml · 地牢服务器示例
synchronization:
map:
# 地牢重置后仍使用同一个地图来源标识。
map-owner-id: '${server-id}'

这样,只要服务器 ID 保持不变,重置前后的地图来源标识就相同,旧地图仍可作为本地地图,随当前地牢的探索继续更新。

定期重置的资源世界:希望保留旧地图画面。 如果玩家已经绘制好了旧资源世界的地图,希望重置后仍能留作纪念,就保留默认的 ${server-id}-${world-uuid}。新世界 UUID 改变后,旧地图会被识别为其他来源,保留已同步保存的旧画面,避免新资源世界相同位置的地形覆盖原来的绘制内容。

尽量在投入使用前确定标识规则

修改规则需要重启服务器,已经记录旧标识的地图会被当作其他来源的地图。建议在地牢或资源世界投入使用前确定规则;移除世界 UUID 时,也应保持各服务器的 server-id 唯一。


🏆 不同服务器上的成就进度​

config.yml · 未知成就
synchronization:
advancements:
# 保留本服没有的成就及其完成进度,关闭后这部分进度可能丢失。
# 各服成就注册表完全一致时,可以关闭以减少扫描开销。
keep-unknown-advancements: true

默认开启,用于保留本服没有注册的成就及其完成进度。

例如,生存服通过数据包添加了自定义成就,而大厅没有安装同一数据包。玩家进入大厅时,这些成就暂时无法识别。保留未知成就后,玩家回到生存服仍能继续原来的进度;关闭后,这部分进度可能在经过大厅并保存后丢失。

什么时候可以关闭?

保留未知成就需要额外扫描和整理数据。如果能确保所有参与同步的服务器始终使用一致的成就注册表,包括自定义数据包及其更新,可以关闭此项,省去这部分扫描开销。


⏱️ 世界保存时如何采集玩家数据​

config.yml · 世界保存
synchronization:
save-triggers:
world-save:
# 世界保存时,一并保存该世界内玩家的快照。
enabled: true

默认开启。服务器保存世界时,Sparrow Sync 会为该世界内的玩家保存快照。世界自动保存通常默认每 6000 tick 执行一次,在 20 TPS 下约为 5 分钟;实际周期取决于服务端的自动保存设置和运行状态。

采集分为两步​

世界保存容易让大量玩家的采集集中到同一时刻。Sparrow Sync 按以下顺序处理:

  1. 玩家所属线程:采集必须同步读取的数据。
  2. 异步线程:补齐剩余数据,再编码并保存快照。
各字段可能存在时间差

这份快照中的所有字段不一定来自同一个瞬间。 异步采集期间玩家仍可能移动、操作物品或改变其他状态,因此部分字段可能存在时间差,不能将其视为完全冻结玩家状态后得到的快照。

为什么采用这种方式​

我们已经对采集开销做了大量优化,但在 1000 人这样的极端在线人数下,将全部数据集中在单线程 Paper 的主线程上读取,仍然可能造成明显的 MSPT 峰值。当前的分段采集方式是在保存及时性、线程要求和主线程负担之间作出的取舍。

1000 人场景的简单测算

按我们的简单测算,1000 人单线程 Paper 场景下,保存时的延迟峰值约为 80 ms,相当于 20 TPS 下不到两个 tick 的时间。

这个数字仅供参考,实际开销会随硬件、玩家数据量和其他插件变化。

市场上的其他同步插件也采用不同方式分散采集压力。有些将采集全部放到异步线程,需要面对读取期间数据被修改的并发风险;有些逐个延迟安排玩家保存,人数越多,排在后面的玩家越晚被采集。分段采集则尽量缩短等待时间,同时减少主线程上的集中开销。


📝 为什么建议保留本地日志​

config.yml · 本地日志
logging:
# 保存详细同步日志,包括控制台中没有显示的记录。
# 推荐保持开启,修改后重启生效。
local-file: true
# 日志保留天数,默认保留两周,启动时清理过期文件。
retention-days: 14

默认开启,建议保留。数据丢失、意外回滚等同步问题往往偶发,等管理员收到反馈时,玩家可能已经切换过几次服务器,很难再还原当时发生了什么。

本地日志会记录:

  • 同步冲突:玩家同步过程中遇到的冲突。
  • 锁的流转:分布式锁的获取与释放。
  • 采集与保存结果:数据从采集到保存的处理记录。

控制台没有显示的许多细节也会写入文件,方便按玩家和时间追查一次完整的同步过程。

这些日志确实很多,也会占用磁盘。但一旦出现数据异常,它们通常是判断问题发生在哪一步的重要依据。关闭后,缺失的现场记录无法补回来。

用保留天数控制磁盘占用

logging.retention-days 默认是 14,保留最近两周的日志。可以根据磁盘空间和排查需要调整这个值;插件会在启动时清理超过保留期限的 .log 和 .log.gz 文件。