本帖最后由 Sssss... 于 2020-3-23 12:05 编辑
本教程的代码部分测试于Bukkit 1.13,理论上所有版本通用
一、思路整理
几天前打算写一个关于基岩的插件(即将发布),但由于基岩在生存模式无法破坏,所以需要通过一些特殊的方式“挖掘”
不久后翻阅Bukkit API文档时看到了一个没用过的事件:PlayerAnimationEvent,文档内的介绍是“玩家动作事件”,只能检测摆臂
于是因为我闲的没事干(可能),就简单测试了一下,得出以下结论:
现在可以通过计数器实现基岩挖掘。经过简单的思考,得出以下过程:
考虑到挖掘的方块变化、手中物品变化时需要清零挖掘进度得到以下较为详细的过程(以下[I]代表Interact事件监听器,[A]代表Animation):
深究一下,会发现isMining变量实际上并没有作用
因为挖掉方块后会因为lastInteractLocation不符而不再执行[A]监听器,若下方为虚空则不会继续触发[A]
于是删除I.1与A.1两步
二、代码实现(由于MCBBS自带的代码显示会出现内容消失等bug,故直接使用文本形式)

是不是觉得少了什么?
于是toBreak方法改为:
private void toBreak(Block block) {
onAnimation下方加一行:
event.getPlayer().sendActionBar("§7基岩挖掘中... §f" + Math.round((double) animationCount / TICKS * 1000) / 10 + "%");
三、最终效果
完美实现破坏基岩:
(我截完这张图以后发现粒子太多了,于是把那边的8改成了3)


由于最后一张图片的链接有敏感词(D.J),请手动输入链接查看(去掉链接中的中括号)
https://i.loli.net/2020/03/22/xRD[]JydQ9q4mG8Ck.png
本教程的代码部分测试于Bukkit 1.13,理论上所有版本通用
一、思路整理
几天前打算写一个关于基岩的插件(即将发布),但由于基岩在生存模式无法破坏,所以需要通过一些特殊的方式“挖掘”
不久后翻阅Bukkit API文档时看到了一个没用过的事件:PlayerAnimationEvent,文档内的介绍是“玩家动作事件”,只能检测摆臂
于是因为我闲的没事干(可能),就简单测试了一下,得出以下结论:
- PlayerAnimationEvent在玩家对着方块按住鼠标时,每tick触发一次
- PlayerInteractEvent仅在玩家按下鼠标的那一刻触发一次,刚好可以用于防止连点器挖掘
- PlayerInteractEvent在Animation之前触发
现在可以通过计数器实现基岩挖掘。经过简单的思考,得出以下过程:
- 记录在两次PlayerInteractEvent之间的PlayerAnimationEvent触发次数
- 当次数达到规定次数(也就是基岩挖掘所需的刻数)时破坏方块并刷新进度
考虑到挖掘的方块变化、手中物品变化时需要清零挖掘进度得到以下较为详细的过程(以下[I]代表Interact事件监听器,[A]代表Animation):
- 以下所有的变量(isMining,animationCount,lastInteractLocation,lastInteractTool)实际应用时应改为Map
- 监听器的各种判断,如是否点击方块、方块种类等省略,此处列举的为思路,并非实际代码实现
- 设挖掘时间为5秒,即100ticks
- [I] 将isMining设置为true // 声明玩家正在挖掘基岩,使Animation监听器工作
- [I] 将animationCount设为0 // 重置进度
- [I] 向lastInteractLocation写入点击的方块位置 // 防止鼠标移动挖掘其他方块
- [I] 向lastInteractTool写入手中的物品 // 防止切换到其他物品
- [A] 若isMining为false(玩家不在挖掘基岩),则跳出监听器
- [A] 若lastInteractLocation或lastInteractTool不匹配(前者使用getTargetBlock方法),则将isMining设置为false并跳出监听器
- [A] animationCount的值增加1 // 计数
- [A] 若animationCount的值为100(即挖掘结束),将isMining设置为false,触发方块破坏
深究一下,会发现isMining变量实际上并没有作用
因为挖掉方块后会因为lastInteractLocation不符而不再执行[A]监听器,若下方为虚空则不会继续触发[A]
于是删除I.1与A.1两步
二、代码实现(由于MCBBS自带的代码显示会出现内容消失等bug,故直接使用文本形式)
然后就可以正常运行了,手持铁镐对着基岩按住五秒后基岩就掉落为物品

是不是觉得少了什么?
- 没有粒子效果使破坏过程过于突兀,于是加上粒子效果:游戏卡顿的时候可以观察到破坏方块的粒子实际上是从4x4x4的64个点创建的
- 因为基岩无法显示挖掘进度,所以可以加一条ActionBar
- 而且挖基岩需要大量时间与精力
(才5秒?),可以让它掉落经验球
于是toBreak方法改为:
private void toBreak(Block block) {
}
onAnimation下方加一行:
event.getPlayer().sendActionBar("§7基岩挖掘中... §f" + Math.round((double) animationCount / TICKS * 1000) / 10 + "%");
三、最终效果
完美实现破坏基岩:
(我截完这张图以后发现粒子太多了,于是把那边的8改成了3)


由于最后一张图片的链接有敏感词(D.J),请手动输入链接查看(去掉链接中的中括号)
https://i.loli.net/2020/03/22/xRD[]JydQ9q4mG8Ck.png
如果挖掘基岩的效果可以配合上NMS的Block Break Animation, 那就会更好了,这里是包的信息
https://wiki.vg/Protocol#Block_Break_Animation
https://wiki.vg/Protocol#Block_Break_Animation
为什么不直接使用原版的挖掘动画?