【1.20+】🌍 WarZRealms —— 个人实例家园世界系统|可扩展 · 可跨服 · 可商业化 · 高性能实例化家园解决方案

原创 付费 【1.20+】🌍 WarZRealms —— 个人实例家园世界系统|可扩展 · 可跨服 · 可商业化 · 高性能实例化家园解决方案 1.7.0

请登录后获取
[MD] # WarZRealms v1.7.0 更新内容总结 ## 一句话总结 修复多服共用 MySQL 时家园数据被非家园服陈旧缓存整行覆盖的根因:非家园服数据层改为只读不写;写库改为"未落库对象只允许 INSERT IGNORE、已加载对象走纯 UPDATE";last_login 单列更新;写库成功后广播缓存失效。 ## 解决了什么问题 - **半径升级反复回弹**:玩家升级边界后,登录非家园服的瞬间 radius 被整行 UPSERT 写回旧值(连同 spawn、简介、has_spawn 一起清掉),binlog 里 100↔105 无限横跳 - **陈旧缓存引擎**:非家园服缓存对象一旦进入永不刷新(putIfAbsent + 失效广播只在删除时发),每次登录/关服都是一次陈旧数据整行写回 ## 根因 非家园服 `realmCache` 中的 `RealmData` 长期不刷新;`updateLastLogin`/`saveAll`/`addRealmAsync` 全部走 `INSERT ... ON DUPLICATE KEY UPDATE` 整行写回,把缓存里的陈旧值(升级前的 radius=100、空出生点、空简介)覆盖共享库中的真实数据;v1.6.8 的创建复核防误创建但防不住缓存对象的反复写回。 ## 具体更新 - `DataManager` 只读模式:`realm-server-id != server-id` 时 addRealm/saveAll/deleteRealm/performCleanup/updateLastLogin 全部短路,启动日志明示 - `RealmData.existsInStorage` 来源标记:未落库对象 `INSERT IGNORE`(行在即拒绝写回+逐出缓存+重载真实数据),已落库对象纯 `UPDATE`(行不在拒绝回填) - `EventListener.updateLastLogin` → `updateLastLoginAsync` 单列更新,不再是整行覆盖载体 - `RealmManager.createRealmInternal` 非家园服硬性拒绝创建(补 `cross-server.enabled` 关闭时的重定向漏洞) - `RedisManager.publishRealmInvalidate`:写库成功后广播 `REALM_INVALIDATE|owner|serverId`,其他服缓存即刻作废;消息带发送者防自循环,兼容旧格式 - `/realm delete` 在非家园服拦下并提示 `messages.realm-readonly` - `config-version` 15 → 16,新消息键自动迁移 ## 对服主/玩家的价值 - 升级过的半径、出生点、简介不再被其他服的登录动作"打回原形" - 多服架构写入收敛到家园服一端,数据归属清晰 - 其他服 GUI 看到的数据也是新的(写后广播失效) ## 升级注意事项 - 三服都换上 1.7.0;家园服保持 `realm-server-id=jiayuan`,其余服不变即可自动进入只读 - 非家园服上的家园修改(设置/删除等)不再保存,需前往家园服操作;GUI 浏览/访问跳转不受影响 - 无数据库结构变更 [/MD]
[MD] # WarZRealms v1.6.9 更新说明 ## 版本信息 - 插件版本:`v1.6.9` - 配置版本:`15`(新增 `unload.*` 五个配置项,自动补齐,旧配置自动备份) - 适用服务端:Paper / Spigot 1.20.1 - 数据库结构:无变更,无需改表 ## 本次更新重点 1. **修复家园世界卸载卡死全服**:玩家退出家园后主线程同步 `unloadWorld`,大世界一次卸载卡 15~40 秒。 2. **新增 `unload.*` 卸载策略**:延迟卸载 + 分批节流 + 可保留常驻家园。 3. **顺带修复**:通过传送(非退出)离开的家园世界此前永不卸载,会一直常驻到重启。 ## 问题:退出家园把全服卡死 ### 现象 - 玩家退出家园/下线后,主线程被卡 15~40 秒,全服无响应,TPS 从 20 掉到个位数 - Watchdog 每次打印主线程转储,停在 `RegionFile.close → FileChannelImpl.force0(Native)`——磁盘 fsync - 世界越大(region 文件越多、脏区块越多)卡得越久 ### 根因 `EventListener.onQuit` 在玩家退出 100 tick 后,主线程直接 `Bukkit.unloadWorld(world, true)`: 一次性同步保存该世界全部脏区块,并逐个关闭所有 region 文件做 fsync。 家园世界一变大(用户环境单世界约 276MB、43 个 region 文件),这一步就是几十秒的主线程阻塞。 另一个隐藏问题:卸载只在"退出"时触发。通过传送(`/realm visit`、回家园再 `/spawn` 等) 离开的家园世界永远不会卸载——40+ 个家园世界常驻就是这么攒出来的,越攒越多, 每次退出的卸载也就越来越重。 ### 修复方式 新增 `RealmUnloadScheduler`,把"立即卸载"改为"空置扫描 + 延迟卸载": - **周期性扫描**所有已加载的家园世界(含下界归组判定),记录每个家园的空置起始时间;有玩家回来即取消 - **延迟卸载**:空置满 `unload.delay`(默认 300 秒)才真正卸载。等待期间服务端的区块系统已经在后台渐进保存/卸载大部分区块,到期 `unloadWorld` 几乎没有落盘量,不再卡主线程 - **分批节流**:每次检查最多卸 `unload.max-per-check`(默认 1)个,大批量卸载分摊到多个周期 - **保留常驻**:`unload.keep-loaded` 可保留最近空置的 N 个家园世界不卸,方便玩家快速回访免二次加载 - 传送离开的世界同样纳入空置扫描,不再常驻到重启 `unload.delay` 设 0 时退化为"空置后尽快卸载"(约 check-interval 秒内),仍比旧的 立即卸载温和;需要完全恢复原行为可以把 `unload.enabled` 关掉(世界常驻,不推荐)。 ## 新增配置 ```yaml unload: enabled: true # 是否自动卸载空置家园世界 delay: 300 # 空置多少秒后卸载,期间回来即取消 check-interval: 200 # 空置检查周期(tick) max-per-check: 1 # 每次检查最多卸载几个家园世界 keep-loaded: 0 # 保留最近空置的 N 个家园常驻 ``` ## 兼容性说明 - `config-version` 升级到 `15`,旧配置自动补齐新项并备份为 `config.yml.v14.backup` - 无数据库结构变更 - `/realm admin reload` 会重载卸载调度器配置 - 行为变化: - 玩家退出后家园世界不再立刻卸载,而是空置 `delay` 秒后卸载(期间回来无缝衔接) - 传送离开的家园世界空置后也会卸载(旧版永不卸载) - 关服时仍同步卸载全部家园世界,逻辑不变 - 删除/重置等主动操作仍是立即卸载,不受影响 [/MD]
[MD] # WarZRealms v1.6.8 更新内容总结 ## 一句话总结 修复家园边界升级后"重启回弹"的根因(游离数据对象把旧半径写回世界边界 + 存储读取失败时用初始半径覆盖真实数据);新增家园生物保护、家园世界默认死亡不掉落;成员数显示改为含主人。 ## 解决了什么问题 - **边界回弹**:玩家升级边界后,重启几次服务器边界悄悄缩回升级前大小 - **生物无保护**:访客进别人家园可以随意击杀动物、村民、宠物 - **死亡掉落**:生成的家园世界按默认规则死亡掉落 - **成员数歧义**:家园列表 `成员: 1/5` 不含主人,实际有主人+成员两人 ## 根因 1. **边界回弹**: - 家园列表页缓存的 `RealmData` 是 `loadAllRealms` 的游离快照,点旧页传送时 `updateWorldBorder` 用旧半径重设世界边界,`WorldBorder` 随 `level.dat` 持久化 → 缩小的边界固定下来 - `loadRealm`/`loadRealms` 读取异常时返回空,`hasRealm` 误报"无家园" → `createRealmInternal` 以 `initial-radius` 新建对象,`ON DUPLICATE KEY UPDATE` 把真实数据整体覆盖回初始值 2. **生物无保护**:`EntityDamageByEntityEvent` 只挡玩家互殴,对非玩家实体零拦截 3. **死亡掉落**:`createOrLoadWorld` 从不设置 gamerule 4. **成员数**:`members_count` 占位符只数 `members` 列表,不含主人 ## 具体更新 - `RealmManager` 新增 `resolveLiveData`:传送/加载世界的所有入口统一解析到缓存活对象,游离快照不再写世界边界;家园已删除时中止而不是用旧快照重建世界 - `createRealmInternal` 创建 0 号家园前防御复核(`hasRealm` 二次确认 + 世界文件夹存在性检查),疑似读取失败立即中止并提示 `realm-load-fail` - `features.protect-entities`(默认开):访客与无 `build` 权限成员无法伤害家园内非玩家实体;攻击识别覆盖近战与弹射物,PvP 判定同步改用同一解析(箭现在也会被拦) - `features.keep-inventory`(默认开):家园主世界与下界创建/加载时开启 `keepInventory` gamerule - `members_count` / `info-members` 显示 `成员数 + 1`(含主人) ## 对服主/玩家的价值 - 升级边界不再莫名缩回去;读取异常时创建家园会先拦下而不是覆盖数据 - 家园动物/宠物有了保护,访客不能随便杀 - 新家园死亡不掉落,符合单机式家园玩法预期 - 成员数与直觉一致 ## 升级注意事项 - `config-version` 升至 `14`,新配置项自动补齐并备份旧配置 - `features.keep-inventory` / `features.protect-entities` 默认开启,均可单独关闭 - 成员数显示含主人(如 `2/5`),成员上限判断不变 - 无数据库结构变更 [/MD]
[MD] ## 具体更新 - 时间切换改为显式状态机;"锁定"取**家园世界**当前时间,且自动避开 1000/13000 哨兵值,保证任何情况下都能切回"默认" - 新增 `resolveLiveData`:设置/权限/边界/成员/黑名单/重置菜单和简介回调统一先取缓存活对象再改 - `DataManager` 缓存回填全部改 `putIfAbsent`,异步加载不再顶替活对象;`getRealm(Async)` 返回缓存规范对象 - 点击改用 `getRawSlot()`,只响应顶部菜单内点击,背包误触不再触发切换 ## 对服主/玩家的价值 - 时间锁定功能按设计可用:默认=时间自然流逝,锁定=冻结当前时刻 - 曾被锁死的家园切回"默认"后时间恢复流动,植物正常生长 - 打开家园列表不再搞坏别人正开着的设置界面 ## 升级注意事项 - `config-version` 无变更(仍为 `13`),无数据库结构变更,YAML/MySQL 均无需改动 - 旧存档的 `time_lock` 数值语义一致,无需迁移 - 建议提醒玩家:之前被锁死的家园重新切一遍到"默认"即可恢复时间流逝 [/MD]
[MD] # WarZRealms v1.6.5 更新内容总结 ## 一句话总结 管理员(OP)现在可以直接在玩家家园里开箱子、放方块了,不用再让玩家把自己加为成员;同时提供 `warzrealms.admin.bypass` 权限节点和开关,方便按服务器情况调整。 ## 解决了什么问题 管理员进入玩家家园后打不开箱子、放不了也拆不了方块,无法巡查和处理违规建筑。 原因是家园权限判定 `canInteract` 只认两种身份——家园主和成员,其余一律拒绝,判定里**既没有 OP 判断也没有权限节点分支**。而插件的 `plugin.yml` 里连 `permissions` 段都没有,不定义任何权限节点,所以 OP 身份在家园里等同于普通路人,权限完全失效。 另外 `getPermission` 默认是 `false`,成员默认零权限,所以连"把管理员加成成员"的老办法也还得家园主手动开权限开关才生效。 ## 具体更新 在 `canInteract` 判定入口加入管理员绕过分支,覆盖放置/破坏(`build`)、容器(`container`)、交互(`interact`)、PvP(`pvp`)四类权限: - **OP 默认生效**,装了就能用,不用任何配置 - 也可以给管理组挂 `warzrealms.admin.bypass` 权限(适合用 LuckPerms 等权限插件、管理员不持有 OP 的服务器) - 新增 `features.admin-bypass` 开关(默认 `true`),服主可随时关掉恢复旧行为 性能保护类的高度限制和方块数量限制不在绕过范围内,管理员同样受约束。 ## 对服主的价值 - 管理员能正常巡查家园、清理违规建筑、核查作弊,不需要先求玩家邀请 - 不再占用宝贵的成员名额(默认 `max-members: 5`),也不用每个家园都重新邀请一遍 - 不想让管理员干涉玩家私人空间的服主,一个开关就能关掉 ## 怎么用 什么都不用做,OP 直接生效。如果服务器用权限插件: ``` /lp group admin permission set warzrealms.admin.bypass true ``` 不想让 OP 自动绕过: ```yaml features: admin-bypass: false ``` 改完 `/realm admin reload` 即可生效。 ## 升级注意事项 - `config-version` 由 `12` 升到 `13`,启动时自动补齐并备份旧配置 - 无数据库结构变更,MySQL / YAML 均无需改动 - **默认行为有变化**:升级后 OP 默认可以进入任何家园建造和开容器。如果管理员同时也是普通玩家、担心误操作或纠纷,把 `features.admin-bypass` 设为 `false` 即可恢复旧行为 - 旧办法(家园主 `/realm invite` → 管理员 `/realm accept` → 家园主开权限开关)依然有效,只是不再必要 [/MD]
[MD] ## 解决了什么问题 玩家跑到自己家园的边界处执行 `/realm setspawn`,边界就会以他脚下为中心整体平移。于是可以: 1. 在边界内造好机器、刷怪塔 2. 走到边界设传送点,边界整体挪走 3. 已造好的机器落到新边界之外,新覆盖的区域又能再建一批 4. 反复操作,白嫖出远超付费半径的面积,绕过 `/realm upgrade` 扩地 ## 具体更新 **1. 修复 `spawn-center-border: false` 把边界钉死在世界原点 `0,0`** 这个开关本来就是用来关掉"边界跟随传送点"的,但它的关闭分支一直把边界中心硬编码成 `0,0`。而随机世界家园的初始出生点通常是 `findSafeSpawnLocation` 从原点向外找到的安全点,往往离原点几百格——边界罩在原点、玩家出生在几百格外,结果一进家园就卡在界外。很多服主因此误以为这个开关坏了,只能继续用会平移边界的默认配置。 改为锁定**家园的初始中心**,即创建/重置时写入世界 spawn 的那个点(模板家园=模板出生点,随机世界=创建时的安全点,下界按 `coordinate-scale` 换算)。不需要新增数据库字段,也不涉及数据迁移。 **2. 新增 `spawn-inside-border-only` 开关(默认关闭)** 开启后,`/realm setspawn` 会校验目标点必须在边界内,越界直接拒绝并提示。用于避免玩家在边界固定后把传送点设到界外、传送进去卡死。 **3. 默认行为完全不变** `spawn-center-border` 默认值仍是 `true`,升级后不改动任何配置就与 `v1.6.3` 完全一致。 [/MD]
  • 插件版本升级到 v1.6.3,配置版本保持 11(本次无新增配置项)
  • 模板菜单改为按槽位记录真实模板文件夹名,不再通过物品显示名反推
  • 修复因 gui.templates.icon_name 带前后缀导致模板名识别错误的问题
  • 模板目录不存在时输出 severe 日志,不再静默失败
  • 新增模板相关排查日志:创建/重置时打印实际使用的模板名
  • 玩家下线时清理模板菜单的槽位映射,避免内存泄漏

本次更新重点​

1. 修复重置家园后模板丢失​

此前使用模板地图创建的家园,执行 /realm reset 后不会沿用原模板,而是随机生成一个新世界。
原因是重置流程在创建新世界时把模板名固定传成了空值,且家园数据里根本没有记录创建时使用的模板。
本版本已调整为:
  • 家园数据新增模板名字段,创建家园时记录所用模板
  • 重置世界时重新复制同一份模板,地形与创建时一致
  • 模板内 template.yml 配置过出生点时,重置后沿用该出生点
  • 模板未配置出生点时,重新寻找安全出生点,避免旧坐标悬空或埋入地下
  • YAML 旧数据缺少模板字段、MySQL 旧表缺少 template_name 列时,重置退化为随机世界,与旧版行为一致

2. 修复重置家园会清空家园数据​

此前重置是「删除数据记录后重新创建」,玩家花钱升的边界等级、添加的成员、填写的简介、设置的时间与天气都会被清空。
本版本改为只重建世界文件夹、保留数据记录:
  • 边界等级、成员、黑名单、简介、家园设置全部保留
  • 只重置地形与 last-reset 时间

3. 修复 /realm delete 二次确认无法完成​

删除最后一个家园时,系统提示「请再次输入 /realm delete 确认」,但再次输入后仍然只提示、不删除,陷入死循环。
原因是代码只在「只剩一个家园」时发出提示便返回,从未记录玩家的确认意图。
本版本已调整为:
  • 新增待确认状态,记录待删除的家园编号与过期时间
  • 第一次输入登记确认意图并提示,再次输入相同编号且在有效期内才真正删除
  • 玩家下线时自动清除待确认状态,避免下次上线误删
  • 管理员 /realm admin delete 不受影响,仍然直接删除

4. 升级费用公式支持自定义​

此前升级费用写死为 base * growth ^ 当前等级。当服主把 initial-radius 调大(例如 100)时,第一次升级的价格会变得极其夸张。
以 base: 50、growth: 1.22、initial-radius: 100 为例,首次升级费用约为 216 亿。
本版本新增 cost.formula,由服主自定义价格曲线:
可用变量:
变量含义
base配置中的 cost.base
growth配置中的 cost.growth
level当前边界等级(升级前的等级)
initial_radius配置中的 initial-radius
支持 + - * / % ^ 与括号,^ 为幂运算且右结合。例如:
  • base * growth ^ level —— 旧版默认公式
  • base * growth ^ (level - initial_radius) —— 按相对初始等级计价(推荐)
  • base + 500 * level —— 线性增长
  • base * (1 + level * 0.5) —— 温和增长
公式写错、结果为负或非有限数时,插件会在控制台告警并自动回退到默认公式,不会崩服。

5. 修复 GUI 重置家园时重置错对象​

多家园场景下,在 GUI 中确认重置时会固定重置编号 0 的家园,而不是当前打开的那个。现已改为重置玩家当前正在操作的家园。

新增配置项​

新增消息文本:delete-confirm-warning、delete-confirm-hint-id。

兼容性说明​

  • config-version 由 10 升级到 11,插件启动时会自动补齐新配置项,并备份旧配置
  • 旧存档无需迁移:没有模板名的老家园重置时仍走随机世界,与旧版完全一致
  • cost.formula 默认为空,即沿用旧公式,升级后价格曲线不会发生变化
  • 需要按相对等级计价时,服主手动填写公式即可
  • MySQL 会自动补 template_name 列,无需手工改表
  • 增加可编辑的默认模板:[default.yml]
  • 首次进入没有专属 NPC 文件的家园时,会自动复制模板为 npcs/<realm_world>.yml。
  • 默认向导使用 location: "spawn",跟随家园出生点。
  • Citizens 已加入 softdepend,避免加载顺序导致 NPC 被禁用。
  • /realm admin reload 会重新加载 NPC 设置,并刷新在线家园的临时 NPC。
[MD] ## WarZRealms v1.6.0 更新总结 ### 核心变更:多家园系统 玩家从"1 人 1 家园"升级为"1 人多家园",每个家园独立管理。 ### 新增指令 指令 说明 /realm create [模板] 创建新家园 /realm switch <编号> 切换家园 /realm myrealms 列出所有家园 /realm home [编号] 回指定编号的家园 /realm delete [编号] 删除指定编号的家园 所有旧指令( info 、 reset 、 setspawn 、 lock 、 day 等)均支持末尾加编号参数。 ### 新增权限 - warzrealms.limit.realms.<N> — 控制最大家园数量 ### 新增 PAPI 变量 - %warzrealms_realm_count% — 家园数量 - %warzrealms_realm_id% — 当前家园编号 ### 新增配置 ``` max-realms: 1 # 默认 1,单家园,向后兼 容 ``` ### 数据兼容 - 旧数据自动视为编号 0 的主家园 - 主家园世界名保持 realm_<UUID> 不变 - 额外家园世界名为 realm_<UUID>_<编号> - YAML: 额外家园存到 realms.<UUID>.realms.<N> - MySQL: 主键自动升级为 (uuid, realm_id) 复合键 [/MD]
后退
顶部 底部