我看到你的区块了

我看到你的区块了

渲染远处站在真实地形上的玩家,远超出渲染距离。服务器流式传输每个被观察玩家周围已存在的区块;客户端接受这些区块并将其交给Voxy,由其自有远距离渲染器绘制。

我看得见你的区块

Fabric Minecraft 客户端需要 Voxy 许可证

我看得见你的区块 会在远超你渲染距离的地方,在真实地形上渲染远处的玩家。与玩家模型漂浮在世界边缘的虚空中不同,服务器会流式传输该玩家所在的区块,而你的客户端会将它们绘制为实际的几何体——具备真实的遮挡关系、实时的方块更新,并与你的 LOD 地形正确地进行深度排序。

⚠️ 客户端需要 Voxy。 Voxy 负责渲染流式传输的地形。没有它,客户端仍然会显示远处的玩家和生物,但他们脚下没有地面,会悬空。专用服务器不需要 Voxy(它是一个仅客户端模组)。参见 工作原理。


✨ 特性

核心功能

  • 🌍 真实地形,而非幽灵: 远处的玩家会被渲染在他们实际占据的区块上,而不是漂浮在虚空中
  • 🚫 零生成开销: 只有服务器上已经加载的区块才会被流式传输——不会新生成、加载或 tick 任何内容
  • 🔄 实时方块更新: 当流式传输的区块中某个方块发生变化时,服务器会重新发送整个区块,客户端会重新接收,因此远处的地形会就地更新——火把、熔岩和建筑都会实时出现
  • ♾️ 远超渲染球体: 通过仅将流式传输的柱子作为额外的渲染根节点注入,地形渲染可远超 Voxy 自身的渲染球体——中间的空盘区域不产生任何开销。Voxy 的投影远平面从硬编码的 48,000 向外推出,远处的玩家也被限制在相同的范围内,因此被观察的玩家和他们脚下的地面总是一起裁剪。该范围实时跟随可见性距离滑块——在滑块最大值时可达到 1,024,000 格——因此提高滑块会立即使地形和玩家同时扩展,无需重新连接。1,024,000 的上限是刻意设置的“绰绰有余”的封顶,并非技术限制(反向 Z 深度意味着它可以几乎无成本地走得更远)
  • 💡 真实光照: 远处的地形使用区块数据包中实际的方块 + 天空光照,因此火把和熔岩会发光,阴影也会正确投射,而不是使用平面近似值
  • 🎯 正确的遮挡: 因为地形确实存在于客户端,山丘后面的玩家实际上是被遮挡的——没有部分遮挡的猜测
  • 📡 选择性握手: 客户端宣告自己;服务器不会向任何未请求的人发送任何内容

进阶功能

  • 👁️ 共享地面上的生物: 坐在被观察玩家周围流式传输地形中的生物也会被显示,并站在同一片真实地面上——绝不会孤立地漂浮
  • 🐴 坐骑随行: 被观察玩家骑乘的任何东西都会与之一同显示——船、马、坐骑的坐骑——即使在零地形的情况下,也不会有人坐在稀薄的空气中
  • 🎚️ 可调节地形范围: 滑块可选择每个被观察玩家周围有多少区块,从仅其所在区块开始,优先向外扩展,直至达到一个半径,并以服务器的渲染距离为上限
  • 🛡️ 隐身感知: 旁观者、隐形和消失的玩家(melius-vanish)会在消耗任何带宽之前在服务器端被过滤掉
  • 📊 带宽受限: 对每个查看者流式传输的区块有硬性上限、可配置的地形范围以及可配置的更新间隔
  • 🤝 优雅降级: 在模组服务器上的原版客户端,或在原版服务器上的模组客户端——两者都会回退到普通的原版行为

⚙️ 工作原理

该模组在网络边界上进行了清晰的分割:

  1. 客户端 → 服务器(握手): 加入时,客户端发送它希望揭示多远距离外的玩家,以及希望每个玩家周围有多少区块的地形。服务器回复一个确认——它自己的渲染距离以及流式传输是否开启——这样客户端就可以让它的滑块和区块存储与现实保持同步。原版客户端从不发送握手信息,也收不到任何内容。
  2. 服务器(流式传输): 每个 tick 间隔,服务器都会在该距离内找到可揭示的玩家,并发送离每个玩家最近的区块——从他们站立的区块开始,按最近优先的顺序扩展(默认为 3×3),并以服务器的渲染距离为上限——外加该地块周围一圈区块的邻居光环。只会发送已驻留的区块,并且只发送原版尚未发送给该查看者的区块。站在可见地块(而非光环)中的生物会与地形一起被揭示。
  3. 客户端(接收): 客户端的区块缓存存储半径被扩大,以便这些超出范围的区块被接收而不是被丢弃。
  4. 客户端(Voxy 交接): 每个流式传输的远距离区块在到达时都会直接转换到 Voxy 的 LOD 存储中——使用区块数据包中实际的方块 + 天空光照——并且 Voxy 通过它自己的远距离渲染器绘制它,与它的 LOD 正确地进行深度排序。超出 Voxy 渲染球体的柱子会额外作为渲染根节点注入,以便它们可以在任何距离绘制,而不会扩大球体。
  5. 实时更新: 当流式传输的区块中某个方块发生变化时,服务器会将该区块(并且仅标记其正在主动流式传输的区块)标记为脏区块,并在下一个间隔重新发送整个区块;客户端会重新接收,而 Voxy 会重新网格化该柱子,因此远处的编辑会显示出来,无需重新连接。

为什么客户端需要 Voxy: 流式传输的区块超出了 Sodium 的渲染距离,因此 Sodium 永远不会将它们编译成网格。Voxy 才是实际将这些地形显示在屏幕上的组件——没有它,该模组的地形部分就什么也不做,远处的玩家会漂浮在虚空中。因此客户端需要它,但仅限客户端:专用服务器只进行流式传输,从不渲染任何东西,所以它既不需要也无法加载 Voxy(一个仅客户端模组)。如果缺少 Voxy,客户端会记录一条响亮的警告。

为什么需要邻居光环: Voxy 的 LOD 网格化器会读取每个区块的邻居来构建它,因此一个没有流式传输邻居的区块无法网格化,并会保持不可见——这会导致任何地块只有内部部分被渲染。在请求的地块周围多流式传输一环,就能让每个可见的区块都有邻居;光环本身永远不会被绘制,也永远不会揭示生物。


📥 安装

在服务器和客户端上都安装 JAR。服务器负责跟踪和流式传输;客户端移除渲染限制。

必需(两端)

  • Fabric Loader 0.16.12+
  • Fabric API
  • Java 25

客户端必需

  • Voxy — 绘制流式传输的远距离地形(仅客户端模组;专用服务器不需要也不应该使用它)

可选

  • Mod Menu — 在游戏中访问配置界面

🖥️ 配置

设置位于 config/i-see-your-chunks.json 中,可以通过 Mod Menu 在游戏中编辑。

选项 描述 默认值
enabled 总开关——如果为 false,则完全禁用模组 true
renderRemotePlayers 渲染远处的玩家(并流式传输他们的区块) true
renderRemoteEntities 渲染位于流式传输地形中的远处生物 true
visibilityDistanceBlocks 揭示远处玩家的距离(渲染最多可达 1,024,000 格) 最大值
chunkRenderCount 每个被观察玩家周围的地形区块数量(0 = 无,按最近优先) 9 (3×3)
streamFarChunks 服务器端:在已揭示的玩家周围流式传输地形 true
sendSpectators 服务器端:揭示旁观模式下的玩家 false
updateIntervalTicks 服务器端:流式传输遍历之间的 tick 数(1–40) 5

注意: streamFarChunks、sendSpectators 和 updateIntervalTicks 只在运行服务器逻辑的机器上生效。其余的是客户端设置。在 chunkRenderCount = 0 时不发送地形,因此只有被观察的玩家——以及他们骑乘的任何东西——会显示;松散的生物只会在有流式传输的地面可站立的地方显示。

更改配置会立即重新发送握手信息,因此流式传输会进行调整,无需重新连接。


✅ 兼容性

模组 状态 备注
Voxy 客户端必需 渲染流式传输的远距离地形;客户端必需,专用服务器不需要
Sodium 完整 与 Sodium 内部没有耦合——更新时不会破坏任何东西
Iris / 光影 完整 流式传输的区块是普通地形,因此光影会正常处理它们
melius-vanish 完整 消失的玩家永远不会被揭示(反射桥接,故障开放)
C2ME 兼容 更快的生成不会改变流式传输的内容——只会发送已加载的区块

📋 技术细节

该模组在以下位置注入:

  • ChunkMap$TrackedEntity.updatePlayer() — 为每个查看者解除跟踪距离上限和区块要求:对玩家及其骑乘的任何东西(包括坐骑链)无条件解除;对于松散的生物,仅当它位于该查看者实际渲染的区块中时(可见地块,绝不是光环)
  • ChunkMap.tick() — 定期根据每个玩家重新评估受管实体,因为生物的可视性会随着远处玩家周围的流式传输区域滑过或滑开而改变
  • ChunkHolder.broadcast() — 当流式传输的远区块发生变化时将其标记为脏区块,以便流式传输器在其下一个间隔重新发送整个区块(只会跟踪它主动流式传输的区块;使用完整重发是因为客户端无法对超出范围且从未缓存的区块应用增量更改)
  • ClientChunkCache.<init> 和 updateViewRadius() — 扩大客户端存储半径,以便流式传输的区块不会因超出范围而被拒绝(两者都需要:半径通常在登录数据包中到达,早于 updateViewRadius 触发)
  • ClientChunkCache.replaceWithPacketData() — 将每个到达的远区块直接转换为 Voxy 的 LOD 存储,并提供我们自己的光照。Voxy 的正常摄取会读取客户端光照引擎,该引擎永远不会为超出渲染距离的区块照明(因此它会静默地什么也不写入);相反,通过 Voxy 自己的转换管道运行,并捕获区块数据包中的真实光照。超出客户端存储半径的区块(数千格之外被观察的玩家)会在解码前被原版拒绝;这些区块会从完整的包缓冲区重新解码为一个临时区块并直接摄取,因此远距离地形可以在任何距离渲染,而无需保存在缓存中
  • ClientPacketListener.handleLevelChunkWithLight() — 捕获区块数据包中实际的方块 + 天空光照,以便上述摄取过程将其提供给 Voxy(原版否则会丢弃超出范围区块的该光照)
  • LevelRenderer.isSectionCompiledAndVisible() — 允许实体在 Sodium 从未编译的 section 中渲染,因为 Voxy 正在绘制那个地面
  • EntityRenderDispatcher.shouldRender() / Entity.shouldRenderAtSqrDistance() — 距离限制覆盖,仍然尊重视锥体裁剪
  • VoxyRenderSystem.computeProjectionMat() — 将 Voxy 硬编码的 48,000 格投影远平面提升到共享的远距渲染边界,以便注入的远区柱子不会被裁剪(仅在存在 Voxy 时应用,由 mixin 配置插件控制)。该边界是根据可见性距离滑块实时计算的(下限 48,000,上限 1,024,000),并且此方法每帧运行,因此范围会立即跟随滑块;受管实体的远平面使用相同的边界,使地形及其上的玩家保持同步

客户端↔服务器握手(入站 ClientHelloPayload,回执 ServerAckPayload)携带偏好设置和服务器实际限制;这里没有任何内容依赖于区块生成,因此它与生成侧的模组保持兼容。

地形范围。 客户端存储半径(约 48 个区块)内的区块会正常通过原版缓存。超出该范围的区块会被直接解码到 Voxy 的 LOD 中,且不会被缓存,因此任意远处玩家周围的地形仍然会渲染——受限于 Voxy 自身紧凑的 LOD 存储,而不是持有的区块。超出 Voxy 渲染球体的柱子会作为额外的渲染根节点被注入,并且对它们解除 Voxy 的距离剔除,因此它们可以渲染到 Voxy 的投影远平面——该模组将其从 Voxy 硬编码的 48,000 提高。该远平面根据可见性距离滑块实时计算(限制在 48,000 的下限和滑块最大值 1,024,000 的上限之间),并与受管实体的远平面共享,因此地形和其上的玩家可以达到相同的距离,并且两者都跟随滑块而无需重新连接。1,024,000 的上限仅仅是因为对于任何实际用途来说都绰绰有余,而不是因为任何技术上的限制——由于深度缓冲区是反向 Z,将其推得更远几乎是无成本的。光照使用每个区块数据包中实际的方块 + 天空光照;如果区块到达时没有光照数据,它会回退到基于高度图的天空近似值。


🗂️ 项目结构

26.2/src/       版本通用代码(配置、网络、流式传输、mixin、客户端逻辑)
26.2/fabric/    Fabric 入口点和特定加载器兼容

🔨 构建

./gradlew :mc26_2-fabric:build

JAR 文件会写入 26.2/fabric/build/libs/。


📜 许可证

本项目采用 GNU Affero 通用公共许可证 v3.0 (AGPL-3.0) 授权。

您可以自由地:

  • ✅ 在整合包中使用
  • ✅ 为个人使用进行修改
  • ✅ 分发修改后的版本(也必须采用 AGPL-3.0)

完整细节请参见 LICENSE 文件。