Level.setBlock()放置方块不可见问题的修复求助
看起来你遇到了模组开发里超常见的客户端-服务端同步坑——自定义物品放的方块只有第一个能正常显示,剩下的全是“隐形”状态,得右键或者重进游戏才会出来,对吧?我之前做模组的时候也踩过这个坑,其实根源特别简单:你只在服务端修改了世界方块,但没把这个变化同步给客户端。
Minecraft是典型的客户端-服务端架构,服务端管世界数据,客户端管渲染。当你用Level.setBlock()的时候,这个操作只会改服务端的世界状态,附近的客户端根本不知道这里的方块变了,自然就不会渲染出来。只有当你右键方块(触发交互同步)或者重进游戏(重新拉取服务端世界数据)的时候,客户端才会拿到正确的方块信息,所以就出现了“隐形方块”的情况。
给你两个最直接的修复方案,选哪个都能解决问题:
方案一:直接用Level.setBlockAndUpdate()代替Level.setBlock()
这是最省心的方法,因为setBlockAndUpdate()这个方法本身就包含了同步逻辑——它在设置方块的同时,会自动调用sendBlockUpdated()把方块变化同步给所有附近的客户端,不用你手动写同步代码。
比如把你代码里类似这样的逻辑:
level.setBlock(pos, blockState, 2);
直接改成:
level.setBlockAndUpdate(pos, blockState);
方案二:手动调用同步方法
如果你还是想用Level.setBlock(),那在设置完方块之后,必须手动调用Level.sendBlockUpdated()来同步:
// 先获取旧的方块状态 BlockState oldState = level.getBlockState(pos); // 设置新的方块状态 boolean success = level.setBlock(pos, newState, 2); if (success) { // 同步更新到客户端,最后一个参数3代表同步状态+通知渲染 level.sendBlockUpdated(pos, oldState, newState, 3); }
另外还要注意一个小细节:所有修改世界的逻辑一定要放在服务端执行,客户端不能直接修改世界状态,否则会出现客户端和服务端状态不一致的情况。你可以用!level.isClientSide()来判断当前是服务端还是客户端,把放置方块的逻辑包在这个判断里:
if (!level.isClientSide()) { // 这里写放置方块+同步的代码 }
按照上面的方法改完之后,你放置的方块应该就能在客户端立刻显示出来,不用再等重进或者交互了。
备注:内容来源于stack exchange,提问作者Murzik Gaming

