如何优化Minecraft Forge 1.19.2中玩家周边方块检测代码?
优化玩家周边方块检测的低CPU方案
先说说你当前代码里的几个核心问题,也是性能浪费的主要来源:
- 重复创建
BlockPos和调用getBlockState:每个判断分支都重新生成坐标、查询方块状态,会产生大量不必要的对象和世界查询开销 - 逻辑运算符优先级错误:
&&优先级高于||,导致你写的CAMPFIRE和FURNACE的亮度条件完全没按预期生效(比如CAMPFIRE的判断会变成(CAMPFIRE || 前面的方块) && 亮度15,逻辑完全混乱) - 手动遍历坐标的方式不够高效,且没有做提前过滤
下面是具体的优化步骤和代码实现:
1. 基础优化:缓存对象+修正逻辑
先把重复的对象查询缓存起来,同时修正逻辑结构,避免重复开销:
// 只创建一次坐标和查询一次方块状态 BlockPos checkPos = new BlockPos(x + sx, y + sy, z + sz); BlockState state = world.getBlockState(checkPos); Block block = state.getBlock(); int brightness = world.getMaxLocalRawBrightness(checkPos); // 用括号包裹带附加条件的判断,修正逻辑优先级 boolean isTargetBlock = block == Blocks.TORCH || block == Blocks.WALL_TORCH || block == Blocks.FIRE || (block == Blocks.CAMPFIRE && brightness == 15) || block == Blocks.LANTERN || block == Blocks.LAVA || block == Blocks.LAVA_CAULDRON || (block == Blocks.FURNACE && brightness == 13);
2. 进阶优化:用集合快速判断方块类型
把目标方块放进静态HashSet,先判断是否在集合内再处理附加条件,这样判断更高效,代码也更易维护:
// 定义成静态常量,只初始化一次 private static final Set<Block> LIGHT_SOURCE_BLOCKS = new HashSet<>(Arrays.asList( Blocks.TORCH, Blocks.WALL_TORCH, Blocks.FIRE, Blocks.LANTERN, Blocks.LAVA, Blocks.LAVA_CAULDRON, Blocks.CAMPFIRE, Blocks.FURNACE )); // 检测逻辑 BlockPos checkPos = new BlockPos(x + sx, y + sy, z + sz); BlockState state = world.getBlockState(checkPos); Block block = state.getBlock(); // 不在目标集合里直接跳过 if (!LIGHT_SOURCE_BLOCKS.contains(block)) { return false; } // 单独处理需要附加条件的方块 int brightness = world.getMaxLocalRawBrightness(checkPos); if (block == Blocks.CAMPFIRE) { return brightness == 15; } else if (block == Blocks.FURNACE) { return brightness == 13; } return true;
3. 遍历方式优化:用Stream替代手动循环
如果你是手动循环sx/sy/sz遍历半径范围,建议用Minecraft内置的BlockPos流API,它内部做了优化,且anyMatch会在找到第一个符合条件的方块时立即终止遍历,比全量遍历更高效:
// 玩家坐标 BlockPos playerPos = new BlockPos(x, y, z); int radius = 10; // 生成半径范围内的坐标流,找到符合条件的就停止 return BlockPos.betweenClosedStream( playerPos.offset(-radius, -radius, -radius), playerPos.offset(radius, radius, radius) ).anyMatch(pos -> { BlockState state = world.getBlockState(pos); Block block = state.getBlock(); if (!LIGHT_SOURCE_BLOCKS.contains(block)) { return false; } int brightness = world.getMaxLocalRawBrightness(pos); if (block == Blocks.CAMPFIRE) { return brightness == 15; } else if (block == Blocks.FURNACE) { return brightness == 13; } return true; });
额外性能优化建议
- 减少检测频率:不要每tick都执行检测,比如只在玩家移动超过1格时,或者每隔5-10tick再检测一次
- 过滤未加载区块:检测前先判断坐标所在区块是否加载(
world.isChunkLoaded(pos.getX() >> 4, pos.getZ() >> 4)),跳过未加载区块的无效查询 - 使用方块标签:如果是Fabric/Forge模组,可以把目标方块注册到自定义Block Tag里,用
state.isIn(YourModTags.LIGHT_SOURCES)判断,更符合Minecraft生态,也方便后续扩展
内容的提问来源于stack exchange,提问作者Eckso
相关产品推荐
相关产品推荐

