Skip to content
This repository was archived by the owner on Aug 7, 2026. It is now read-only.

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

FapSkinRefresh

FAPIXEL 玩家隐身修复插件 — 针对网易中国版 3.9(V860 协议)客户端的玩家隐身问题


一、问题背景

网易我的世界中国版 3.9 客户端更新(V860 协议)后,玩家偶尔完全隐身——皮肤、头顶 nametag、手持物品全部不显示,只剩影子。具体现象:

  • 默认皮肤(史蒂夫)高概率触发
  • 部分玩家看得到、部分看不到(视角相关)
  • 有时自己看自己也隐身(第三人称 / 暂停页面)
  • 可能自动恢复,然后又隐身
  • 在多服切换(WaterdogPE 代理跳转)后尤其频繁

已有的修复手段

插件 所在层 作用 局限
NetEasePlayerListFix WaterdogPE 代理层 拦截 PlayerListPacket(ADD),对 V860 客户端做三态去重(ADD / SUPPRESS / REPLACE),避免重复 ADD 触发 V860 渲染 bug 只拦截 PlayerListPacket;当客户端内部状态已损坏,代理会因皮肤相同而抑制修复包
SkinValidationFix Nukkit 后端 修复 NukkitMaster 皮肤验证请求中 geo_list 字段导致验证失败的问题 只解决验证阶段,不解决渲染阶段

核心矛盾:当 V860 客户端的 PlayerList 条目因内部 bug 失效后,服务端尝试通过 PlayerListPacket(ADD) 修复,但代理层发现皮肤相同 → 抑制 ADD → 客户端永远收不到修复包 → 玩家隐形,直到客户端自己偶然恢复。


二、解决原理

利用 WaterdogPE 代理层只拦截 PlayerListPacket 这一特性,改用代理不拦截的数据包类型来强制刷新客户端状态:

代理层拦截范围(NetEasePlayerListFix)
    └── PlayerListPacket ✗ 被拦截去重

以下数据包代理均不拦截:
    ├── PlayerSkinPacket  ✓ 直接到达客户端
    ├── RemoveEntityPacket ✓ 直接到达客户端
    └── AddPlayerPacket   ✓ 直接到达客户端

三道防线

防线 机制 默认间隔 修复场景 副作用
① 皮肤数据刷新 向所有在线玩家互发 PlayerSkinPacket 60 秒 条目存在但皮肤数据失效
② 实体重置 despawnFromAll() + 延迟 spawnToAll() 180 秒 实体渲染完全失败、引用失效 极短暂闪烁(约 1 tick)
③ 进服延迟刷新 玩家进服 5 秒后向所有人发皮肤包 事件触发 进服时初始皮肤未同步

客户端请求刷新(可选增强)

插件注册了 PyRpc 事件 RequestSkinRefreshEvent。客户端可通过 self.NotifyToServer("RequestSkinRefreshEvent", {}) 主动请求,服务端会只刷新请求者附近 128 格内的玩家(精准刷新,避免全服广播)。

目前无需修改客户端行为包即可工作。客户端主动请求是后续锦上添花的增强项。


三、安装与配置

环境要求

  • 服务端核心:Nukkit-MOT
  • 依赖插件:NukkitMaster(提供 PyRpc 通信能力)

安装

FapSkinRefresh.jar 放入 Nukkit 子服的 plugins/ 目录,重启服务端。

配置文件

配置位于 plugins/FapSkinRefresh/config.yml,首次启动自动生成:

# 定期皮肤刷新
refresh:
  enabled: true
  interval: 60        # 刷新间隔(秒)
  batch_size: 10      # 每批处理的玩家对数量

# 全量实体刷新(despawn + spawn,有极短闪烁)
full_refresh:
  enabled: true
  interval: 180       # 刷新间隔(秒)
  batch_size: 5       # 每轮处理的玩家数量
  spawn_delay: 1      # despawn 和 spawn 之间的延迟(tick)

# 客户端请求刷新
client_request:
  enabled: true
  cooldown: 15        # 请求冷却(秒)
  radius: 128         # 刷新半径(格)

# 进服延迟刷新
join_refresh:
  enabled: true
  delay: 5            # 进服后延迟(秒)

debug: false          # 诊断日志

调优建议

  • 如果 180 秒的实体重置闪烁明显 → full_refresh.enabled: false
  • 如果隐身问题严重 → 降低 refresh.interval 到 30 秒
  • 排查问题 → debug: true 观察控制台日志

四、管理命令

/fapskin                     查看运行状态
/fapskin refresh <玩家名>     手动刷新指定玩家的皮肤
/fapskin refresh all         手动触发全量刷新(皮肤 + 实体)
/fapskin reload              重载配置文件

需要权限节点 fapskin.admin(默认 OP)。


五、后续开发方向

本项目目前是纯服务端被动防御方案。以下方向按优先级排列:

1. 客户端主动刷新请求(推荐下一步)

⚠️ 方案演进说明(原文已标记删除线,保留以记录思考过程)

定期(如每 10 秒)检测附近玩家的渲染状态,发现隐身玩家时立即通过 PyRpc 请求 RequestSkinRefreshEvent,配合服务端的精准刷新(半径过滤),实现即时修复 + 极低开销。

为什么不可行: 网易中国版 ModSDK 的客户端 Python API(ClientSystem / CompFactory)能获取的是实体的逻辑数据——实体 ID、位置坐标、类型标识符、血量等(参见中国版 ModSDK 文档 — 实体组件,如 GetEntitiesGetEntityById 等接口)。但 ModSDK 没有任何接口能查询实体的渲染层面状态——即"该实体的皮肤贴图是否已加载""模型是否正确渲染""玩家是否在画面上可见"这些信息属于客户端渲染引擎的内部状态,ModSDK 完全不暴露这一层。因此客户端无法主动检测到某个玩家已经隐身,"发现隐身 → 请求修复"的反应式链路从根本上不成立。

修正后的实际方案:客户端事件驱动的预防性刷新

既然无法检测,改为在已知的高风险时机主动触发刷新请求:

  • 跨服跳转完成后(WaterdogPE 切服是隐身的最高频诱因)
  • 维度切换后(下界 / 末地 / 自定义维度切换)
  • 玩家自己切换到第三人称视角时

客户端在这些事件触发后,通过 PyRpc 主动请求 RequestSkinRefreshEvent,服务端只刷新请求者附近 128 格内的玩家(精准刷新,避免全服广播)。这比服务端定时全量广播更精准、开销更低,本质上是预防性刷新而非反应性修复。

2. 自适应刷新策略

当前定时任务是固定间隔。可增强为:

  • 记录每次刷新后客户端的反馈(是否有玩家重新出现) — 同样不可行,客户端无法感知渲染结果(原因同上)
  • 在服务端侧统计高频时段(如跨服高峰期),动态提高刷新频率
  • 对稳定时段降低频率,减少不必要的数据包开销

3. 代理层增强(WaterdogPE 插件)

目前利用的是"代理不拦截非 PlayerListPacket"这个事实。更彻底的方案是在代理层增加:

  • PlayerSkinPacket 做健康检查(皮肤数据是否完整)
  • 主动注入修复包,而不是依赖后端插件

4. 多服去重

当前每个子服各自运行刷新任务。在跨服跳转场景下,可考虑:

  • 在代理层(或独立服务)统一管理刷新状态
  • 避免玩家刚跳转就被两个子服同时刷新造成冲突

5. 数据指标

  • 记录隐身发生的频率、恢复时间
  • 为后续优化提供数据支撑

六、技术栈

  • 语言:Java 21
  • 服务端:Nukkit-MOT(基岩版第三方服务端)
  • 依赖:NukkitMaster(PyRpc 通信框架)
  • 通信协议:基岩版协议(PlayerSkinPacket / AddPlayerPacket / RemoveEntityPacket)

七、项目结构

FapSkinRefresh/
├── src/main/java/cn/fapixel/fapskinrefresh/
│   └── FapSkinRefresh.java        # 主类(监听器 + 定时任务 + 命令)
├── src/main/resources/
│   ├── plugin.yml                 # 插件描述
│   └── config.yml                 # 配置文件
├── libs/                          # 依赖 jar(gitignore,不入库)
├── build.py                       # 编译 + 打包 + 部署脚本
└── README.md

FAPIXEL 小游戏服务器 · FunnyArenaPixel

About

FAPIXEL 玩家隐身修复插件 — 针对 V860 (3.9) 客户端,通过 PlayerSkinPacket + despawn/spawn 绕过代理去重

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages