Geyser方块状态映射:解决Java与基岩版方块ID差异
方块差异的技术痛点
Minecraft Java版与基岩版(Bedrock Edition)采用截然不同的方块标识系统:Java版使用字符串标识符(如minecraft:chest[facing=north]),而基岩版采用数值ID+数据值的组合方式。这种差异导致直接连接时出现方块显示错误、碰撞体积异常等问题。Geyser通过方块状态映射系统解决这一核心矛盾,其实现逻辑集中在core/src/main/java/org/geysermc/geyser/registry/mappings/util/CustomBlockMapping.java与CustomBlockStateMapping.java中。
数据结构设计
1. 自定义方块映射记录
public record CustomBlockMapping(
@NonNull CustomBlockData data,
@NonNull Map<String, CustomBlockStateMapping> states,
@NonNull String javaIdentifier,
boolean overrideItem
) {}
data: 存储方块基础属性(名称、材质、硬度等)states: 状态映射表,键为Java状态字符串(如facing=south),值为对应的基岩版状态定义javaIdentifier: Java版方块标识符(如minecraft:chest)overrideItem: 是否覆盖原版物品行为
2. 方块状态映射记录
public record CustomBlockStateMapping(
@NonNull CustomBlockState state,
BoxComponent extendedCollisionBox
) {}
state: 基岩版状态定义,包含数值ID和状态值extendedCollisionBox: 扩展碰撞箱定义,解决不同版本碰撞体积差异
注册流程解析
1. 注册表初始化
BlockRegistries类(引用自bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java)维护关键映射关系:
JAVA_BLOCK_STATE_IDENTIFIER_TO_ID: Java状态字符串到数值ID的映射CUSTOM_BLOCK_STATE_OVERRIDES: 自定义方块状态覆盖表EXTENDED_COLLISION_BOXES: 碰撞箱扩展定义
2. 映射加载流程
加载逻辑在CustomBlockRegistryPopulator.java中实现,通过遍历Java版方块注册表,为每个需要转换的方块创建映射规则。
运行时转换机制
当Java服务器发送方块数据时,Geyser执行以下步骤:
- 从方块数据包中提取Java状态字符串
- 调用
BlockRegistries.JAVA_BLOCK_STATE_IDENTIFIER_TO_ID获取数值ID - 查找CustomBlockStateMapping获取基岩版状态
- 生成包含正确ID和碰撞箱数据的基岩版数据包
关键代码示例(来自Spigot平台实现):
int javaBlockId = ...; // 获取Java版方块ID
int bedrockBlockId = session.getBlockMappings()
.getBedrockBlockId(BlockRegistries.JAVA_BLOCK_STATE_IDENTIFIER_TO_ID
.getOrDefault(javaBlockId, Block.JAVA_AIR_ID));
冲突解决方案
1. 状态冲突处理
当Java版状态组合在基岩版不存在时(如活塞的extended状态),Geyser通过CustomBlockStateMapping.state()提供替代状态定义。
2. 碰撞箱适配
通过extendedCollisionBox字段定义额外碰撞体积,解决如台阶、半砖等方块的碰撞检测问题,实现代码位于CustomBlockStateMapping.java的构造函数中。
扩展与自定义
服务器管理员可通过修改JSON配置文件添加自定义映射,无需修改源码:
- 在配置目录创建
custom_blocks文件夹 - 添加包含方块状态映射的JSON文件
- 设置
overrideItem=true覆盖原版物品行为
详细配置规范参见CustomBlockMapping.java的JavaDoc注释。
性能优化
- 预加载机制:启动时完成所有映射计算,运行时直接查表
- 版本隔离:为不同协议版本维护独立映射表(BlockRegistryPopulator.java)
- 内存缓存:常用方块状态缓存至堆外内存,减少GC压力
未来改进方向
- 动态状态生成:支持运行时计算复杂状态映射
- 可视化编辑器:开发配套工具简化映射配置
- 冲突检测:自动识别并提示不兼容的状态定义
通过这套映射系统,Geyser成功实现了跨版本方块数据的无缝转换,为Java与基岩版互联互通奠定了技术基础。核心代码的模块化设计使得添加新方块支持或调整映射规则仅需修改配置文件,极大降低了维护成本。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



