You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Geyser的PlayerInteractEvent问题?求技术实现指导

Geyser跨平台交互问题修复指南

背景说明

我曾在Geyser的GitHub仓库提交问题《Shooting Projectiles via Plugin is Glitchy #2913》,我的小游戏依赖PlayerInteractEvent,这个问题对我影响极大。之后有用户chrismwiggs提交了几个类似问题,其中第二个问题《Left click events not detected by other plugins when punching "air"... #2113》提到了一种可能的解决方案。当时我认为自行修复工作量过大,等待官方解决,后来发现该问题可能不会被修复,便取消了服务器的跨平台支持。现在我想恢复跨平台支持,打算fork Geyser自行修改,但我仅处于插件开发进阶新手阶段,特请教以下问题的解决方案:


问题解答

1. 是否需要使用ServerboundSwingPacket或其他组件以实现全Bedrock平台兼容

需要。Bedrock端空手左键点击空气时,不会像Java端那样触发PlayerInteractEvent,核心原因是Geyser默认没有将Bedrock的挥动手势转换为Java端的ServerboundSwingPacket。要让插件捕捉到这类交互事件,必须在Bedrock玩家做出挥动手势时,向Java服务器发送对应的挥包,同时还要处理投射物发射的同步逻辑,确保Bedrock端操作能正确触发Java端的PlayerInteractEvent。

2. 应在Geyser源码的何处添加相关代码

核心修改位置在Geyser的Bedrock交互事件处理模块:

  • 找到处理Bedrock玩家挥动手势的类,通常是BedrockPlayerSession或InteractionTranslator(具体路径可能因Geyser版本略有差异,比如org.geysermc.geyser.session.cache.InteractionCache或org.geysermc.geyser.translator.protocol.bedrock.PlayerActionTranslator)
  • 另外需要在向Java服务器发包的逻辑中添加挥包发送逻辑,相关代码位于org.geysermc.geyser.network.session.GeyserSession的发包方法附近

3. 需要添加的具体代码内容

以下是基于Geyser常见版本的示例代码(需根据你fork的版本调整细节):

步骤1:捕获Bedrock挥动手势并发送对应数据包

在处理BedrockPlayerActionPacket的方法(比如PlayerActionTranslator的translate方法)中,添加对挥动手势动作的判断:

if (packet.getAction() == PlayerAction.START_SWING || packet.getAction() == PlayerAction.SWING_ARM) {
    // 向Java服务器发送挥包
    ServerboundSwingPacket swingPacket = new ServerboundSwingPacket(Hand.MAIN_HAND);
    session.sendDownstreamPacket(swingPacket);
    
    // 额外处理投射物发射场景(对应你的#2913问题)
    if (session.getPlayerInventory().getItemInHand(Hand.MAIN_HAND).getType().isProjectileWeapon()) {
        // 发送使用物品包触发PlayerInteractEvent
        ServerboundUseItemPacket useItemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND);
        session.sendDownstreamPacket(useItemPacket);
    }
}

步骤2:同步空手点击的交互状态

如果需要更精准触发PlayerInteractEvent,可在InteractionCache中添加空手点击的处理逻辑,同步Bedrock端交互状态到Java端:

// 在处理Bedrock交互更新的方法中
public void handleSwing(Hand hand) {
    // 检查是否为空手状态,发送交互包
    if (session.getPlayer().isOnGround() && session.getPlayerInventory().getItemInHand(hand).isEmpty()) {
        ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(
            session.getPlayerEntityId(),
            ServerboundInteractPacket.Action.ATTACK,
            session.getPlayer().getPosition()
        );
        session.sendDownstreamPacket(interactPacket);
    }
}

注意:以上代码仅为示例,实际需根据你fork的Geyser版本的代码结构调整,不同版本的数据包类名、枚举值可能存在差异,建议先通读Geyser的交互处理逻辑后再进行修改。


内容的提问来源于stack exchange,提问作者ThrownRedstone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 19:01:21